* generator/ClassBase.cs (ParseImplements): record both managed
and unmanaged interface declarations. (Implements): check recursively * generator/ObjectGen.cs (Generate): output managed interfaces * gtk/Gtk.metadata: make Container implement IEnumerable * gtk/Container.custom (GetEnumerator): implement (a simplified form of Children). (AllChildren): add this (which accumulates the results of Forall()). (ForAll): mark ForAll(bool,CallbackInvoker) obsolete and add a ForAll(bool,Gtk.Callback) overload to replace it. * sample/PolarFixed.cs: new silly but fully-functional demo of how to subclass container. * sample/CustomNotebook.cs: kill this, since it was really complicated, and never fully functional. * sample/GtkDemo/DemoImages.cs (ToggleSensitivity): Use foreach directly on the container, rather than on its .Children. svn path=/trunk/gtk-sharp/; revision=42805
This commit is contained in:
parent
c7b382782e
commit
b8126ce3af
11 changed files with 439 additions and 678 deletions
26
ChangeLog
26
ChangeLog
|
@ -1,3 +1,29 @@
|
||||||
|
2005-04-11 Dan Winship <danw@novell.com>
|
||||||
|
|
||||||
|
* generator/ClassBase.cs (ParseImplements): record both managed
|
||||||
|
and unmanaged interface declarations.
|
||||||
|
(Implements): check recursively
|
||||||
|
|
||||||
|
* generator/ObjectGen.cs (Generate): output managed interfaces
|
||||||
|
|
||||||
|
* gtk/Gtk.metadata: make Container implement IEnumerable
|
||||||
|
|
||||||
|
* gtk/Container.custom (GetEnumerator): implement (a simplified
|
||||||
|
form of Children).
|
||||||
|
(AllChildren): add this (which accumulates the results of
|
||||||
|
Forall()).
|
||||||
|
(ForAll): mark ForAll(bool,CallbackInvoker) obsolete and add a
|
||||||
|
ForAll(bool,Gtk.Callback) overload to replace it.
|
||||||
|
|
||||||
|
* sample/PolarFixed.cs: new silly but fully-functional demo of
|
||||||
|
how to subclass container.
|
||||||
|
|
||||||
|
* sample/CustomNotebook.cs: kill this, since it was really
|
||||||
|
complicated, and never fully functional.
|
||||||
|
|
||||||
|
* sample/GtkDemo/DemoImages.cs (ToggleSensitivity): Use foreach
|
||||||
|
directly on the container, rather than on its .Children.
|
||||||
|
|
||||||
2005-04-11 Mike Kestner <mkestner@novell.com>
|
2005-04-11 Mike Kestner <mkestner@novell.com>
|
||||||
|
|
||||||
* gtk/Quit.custom : obsolete AddFull and implement Add properly.
|
* gtk/Quit.custom : obsolete AddFull and implement Add properly.
|
||||||
|
|
|
@ -1,3 +1,7 @@
|
||||||
|
2005-04-08 Dan Winship <danw@novell.com>
|
||||||
|
|
||||||
|
* en/Gtk/Container.xml: document new children stuff
|
||||||
|
|
||||||
2005-04-04 Dan Winship <danw@novell.com>
|
2005-04-04 Dan Winship <danw@novell.com>
|
||||||
|
|
||||||
* en/Pango/Scale.xml: update
|
* en/Pango/Scale.xml: update
|
||||||
|
|
|
@ -532,12 +532,69 @@
|
||||||
</ReturnValue>
|
</ReturnValue>
|
||||||
<Parameters />
|
<Parameters />
|
||||||
<Docs>
|
<Docs>
|
||||||
<summary>Obtains the the container's non-internal children.</summary>
|
<summary>Obtains an array of the container's (non-internal) children.</summary>
|
||||||
<returns>An array of non-internal children.</returns>
|
<returns>An array of non-internal children.</returns>
|
||||||
<remarks>
|
<remarks>
|
||||||
<para>
|
<para>
|
||||||
See <see cref="M:Gtk.Container.Forall" /> for details on what constitutes an "internal" child.
|
Returns the container's non-internal children; that is, generally, the
|
||||||
|
children that were explicitly added to the container by the application, as
|
||||||
|
opposed to those widgets that are internal implementation details of the
|
||||||
|
container.
|
||||||
</para>
|
</para>
|
||||||
|
<para>
|
||||||
|
If you simply want to do a <see langword="foreach" /> loop on the
|
||||||
|
container's children, you do not need to use the Children property.
|
||||||
|
Just do:
|
||||||
|
</para>
|
||||||
|
<example>
|
||||||
|
<code lang="C#">
|
||||||
|
foreach (Widget w in myContainer) {
|
||||||
|
// Do something with w
|
||||||
|
}
|
||||||
|
</code>
|
||||||
|
</example>
|
||||||
|
</remarks>
|
||||||
|
</Docs>
|
||||||
|
</Member>
|
||||||
|
<Member MemberName="GetEnumerator">
|
||||||
|
<MemberSignature Language="C#" Value="public virtual System.Collections.IEnumerator GetEnumerator ();" />
|
||||||
|
<MemberType>Method</MemberType>
|
||||||
|
<ReturnValue>
|
||||||
|
<ReturnType>System.Collections.IEnumerator</ReturnType>
|
||||||
|
</ReturnValue>
|
||||||
|
<Parameters />
|
||||||
|
<Docs>
|
||||||
|
<summary>Returns an <see cref="T:System.Collections.IEnumerator" /> for the container's children</summary>
|
||||||
|
<returns>a <see cref="T:System.Collections.IEnumerator" /></returns>
|
||||||
|
<remarks>
|
||||||
|
<para>
|
||||||
|
<see cref="T:Gtk.Container" /> implements
|
||||||
|
<see cref="T:System.Collections.IEnumerable" />, so you can iterate
|
||||||
|
through its children like this:
|
||||||
|
</para>
|
||||||
|
<example>
|
||||||
|
<code lang="C#">
|
||||||
|
foreach (Widget w in myContainer) {
|
||||||
|
// Do something with w
|
||||||
|
}
|
||||||
|
</code>
|
||||||
|
</example>
|
||||||
|
</remarks>
|
||||||
|
</Docs>
|
||||||
|
</Member>
|
||||||
|
<Member MemberName="AllChildren">
|
||||||
|
<MemberSignature Language="C#" Value="public System.Collections.IEnumerable AllChildren { get; };" />
|
||||||
|
<MemberType>Property</MemberType>
|
||||||
|
<ReturnValue>
|
||||||
|
<ReturnType>System.Collections.IEnumerable</ReturnType>
|
||||||
|
</ReturnValue>
|
||||||
|
<Parameters />
|
||||||
|
<Docs>
|
||||||
|
<summary>Allows you to enumerate all of the container's children.</summary>
|
||||||
|
<returns>an <see cref="T:System.Collections.IEnumerable" /></returns>
|
||||||
|
<remarks>
|
||||||
|
Enumerates all of the container's children, including those widgets that are
|
||||||
|
internal implementation details of the container.
|
||||||
</remarks>
|
</remarks>
|
||||||
</Docs>
|
</Docs>
|
||||||
</Member>
|
</Member>
|
||||||
|
@ -573,7 +630,7 @@
|
||||||
</remarks>
|
</remarks>
|
||||||
</Docs>
|
</Docs>
|
||||||
</Member>
|
</Member>
|
||||||
<Member MemberName="ForAll">
|
<Member MemberName="ForAll" Deprecated="true">
|
||||||
<MemberSignature Language="C#" Value="protected virtual void ForAll (bool include_internals, Gtk.Container+CallbackInvoker invoker);" />
|
<MemberSignature Language="C#" Value="protected virtual void ForAll (bool include_internals, Gtk.Container+CallbackInvoker invoker);" />
|
||||||
<MemberType>Method</MemberType>
|
<MemberType>Method</MemberType>
|
||||||
<ReturnValue>
|
<ReturnValue>
|
||||||
|
@ -585,9 +642,32 @@
|
||||||
</Parameters>
|
</Parameters>
|
||||||
<Docs>
|
<Docs>
|
||||||
<summary>Run a given callback for every object inside this container.</summary>
|
<summary>Run a given callback for every object inside this container.</summary>
|
||||||
<param name="include_internals">a <see cref="T:System.Boolean" />, whether to include this container's children's children when running the callback.</param>
|
<param name="include_internals">a <see cref="T:System.Boolean" />, whether to include "internal" children when running the callback.</param>
|
||||||
<param name="invoker">a <see cref="T:Gtk.Container+CallbackInvoker" /></param>
|
<param name="invoker">a <see cref="T:Gtk.Container+CallbackInvoker" /></param>
|
||||||
<remarks />
|
<remarks>
|
||||||
|
Deprecated: overload <see cref="M:Gtk.Container.Forall(System.Boolean,Gtk.Callback)" /> instead.
|
||||||
|
</remarks>
|
||||||
|
</Docs>
|
||||||
|
</Member>
|
||||||
|
<Member MemberName="ForAll">
|
||||||
|
<MemberSignature Language="C#" Value="protected virtual void ForAll (bool include_internals, Gtk.Callback callback);" />
|
||||||
|
<MemberType>Method</MemberType>
|
||||||
|
<ReturnValue>
|
||||||
|
<ReturnType>System.Void</ReturnType>
|
||||||
|
</ReturnValue>
|
||||||
|
<Parameters>
|
||||||
|
<Parameter Name="include_internals" Type="System.Boolean" />
|
||||||
|
<Parameter Name="callback" Type="Gtk.Callback" />
|
||||||
|
</Parameters>
|
||||||
|
<Docs>
|
||||||
|
<summary>Run a given callback for every object inside this container.</summary>
|
||||||
|
<param name="include_internals">a <see cref="T:System.Boolean" />, whether to include "internal" children when running the callback.</param>
|
||||||
|
<param name="callback">a <see cref="T:Gtk.Callback" /></param>
|
||||||
|
<remarks>
|
||||||
|
Overload this in subclasses of Gtk.Container to implement the
|
||||||
|
<see cref="M:Gtk.Container.Foreach" /> and <see cref="M:Gtk.Container.Forall" />
|
||||||
|
methods.
|
||||||
|
</remarks>
|
||||||
</Docs>
|
</Docs>
|
||||||
</Member>
|
</Member>
|
||||||
<Member MemberName="ChildType">
|
<Member MemberName="ChildType">
|
||||||
|
|
|
@ -33,7 +33,8 @@ namespace GtkSharp.Generation {
|
||||||
protected Hashtable props = new Hashtable();
|
protected Hashtable props = new Hashtable();
|
||||||
protected Hashtable sigs = new Hashtable();
|
protected Hashtable sigs = new Hashtable();
|
||||||
protected Hashtable methods = new Hashtable();
|
protected Hashtable methods = new Hashtable();
|
||||||
protected ArrayList interfaces = null;
|
protected ArrayList interfaces = new ArrayList();
|
||||||
|
protected ArrayList managed_interfaces = new ArrayList();
|
||||||
protected ArrayList ctors = new ArrayList();
|
protected ArrayList ctors = new ArrayList();
|
||||||
|
|
||||||
private bool ctors_initted = false;
|
private bool ctors_initted = false;
|
||||||
|
@ -101,7 +102,7 @@ namespace GtkSharp.Generation {
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case "implements":
|
case "implements":
|
||||||
interfaces = ParseImplements (member);
|
ParseImplements (member);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case "constructor":
|
case "constructor":
|
||||||
|
@ -193,18 +194,17 @@ namespace GtkSharp.Generation {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private ArrayList ParseImplements (XmlElement member)
|
private void ParseImplements (XmlElement member)
|
||||||
{
|
{
|
||||||
ArrayList ifaces = new ArrayList ();
|
|
||||||
|
|
||||||
foreach (XmlNode node in member.ChildNodes) {
|
foreach (XmlNode node in member.ChildNodes) {
|
||||||
if (node.Name != "interface")
|
if (node.Name != "interface")
|
||||||
continue;
|
continue;
|
||||||
XmlElement element = (XmlElement) node;
|
XmlElement element = (XmlElement) node;
|
||||||
ifaces.Add (element.GetAttribute ("cname"));
|
if (element.HasAttribute ("cname"))
|
||||||
|
interfaces.Add (element.GetAttribute ("cname"));
|
||||||
|
else if (element.HasAttribute ("name"))
|
||||||
|
managed_interfaces.Add (element.GetAttribute ("name"));
|
||||||
}
|
}
|
||||||
|
|
||||||
return ifaces;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
protected bool IgnoreMethod (Method method)
|
protected bool IgnoreMethod (Method method)
|
||||||
|
@ -273,7 +273,7 @@ namespace GtkSharp.Generation {
|
||||||
if (p == null && Parent != null)
|
if (p == null && Parent != null)
|
||||||
p = Parent.GetMethodRecursively (name, true);
|
p = Parent.GetMethodRecursively (name, true);
|
||||||
|
|
||||||
if (check_self && p == null && interfaces != null) {
|
if (check_self && p == null) {
|
||||||
foreach (string iface in interfaces) {
|
foreach (string iface in interfaces) {
|
||||||
ClassBase igen = SymbolTable.Table.GetClassGen (iface);
|
ClassBase igen = SymbolTable.Table.GetClassGen (iface);
|
||||||
p = igen.GetMethodRecursively (name, true);
|
p = igen.GetMethodRecursively (name, true);
|
||||||
|
@ -310,7 +310,7 @@ namespace GtkSharp.Generation {
|
||||||
if (p == null && Parent != null)
|
if (p == null && Parent != null)
|
||||||
p = Parent.GetSignalRecursively (name, true);
|
p = Parent.GetSignalRecursively (name, true);
|
||||||
|
|
||||||
if (check_self && p == null && interfaces != null) {
|
if (check_self && p == null) {
|
||||||
foreach (string iface in interfaces) {
|
foreach (string iface in interfaces) {
|
||||||
ClassBase igen = SymbolTable.Table.GetClassGen (iface);
|
ClassBase igen = SymbolTable.Table.GetClassGen (iface);
|
||||||
p = igen.GetSignalRecursively (name, true);
|
p = igen.GetSignalRecursively (name, true);
|
||||||
|
@ -324,8 +324,10 @@ namespace GtkSharp.Generation {
|
||||||
|
|
||||||
public bool Implements (string iface)
|
public bool Implements (string iface)
|
||||||
{
|
{
|
||||||
if (interfaces != null)
|
if (interfaces.Contains (iface))
|
||||||
return interfaces.Contains (iface);
|
return true;
|
||||||
|
else if (Parent != null)
|
||||||
|
return Parent.Implements (iface);
|
||||||
else
|
else
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
|
@ -140,12 +140,15 @@ namespace GtkSharp.Generation {
|
||||||
di.objects.Add (CName, QualifiedName);
|
di.objects.Add (CName, QualifiedName);
|
||||||
sw.Write (" : " + cs_parent);
|
sw.Write (" : " + cs_parent);
|
||||||
}
|
}
|
||||||
if (interfaces != null) {
|
|
||||||
foreach (string iface in interfaces) {
|
foreach (string iface in interfaces) {
|
||||||
if (Parent != null && Parent.Implements (iface))
|
if (Parent != null && Parent.Implements (iface))
|
||||||
continue;
|
continue;
|
||||||
sw.Write (", " + table.GetCSType (iface));
|
sw.Write (", " + table.GetCSType (iface));
|
||||||
}
|
}
|
||||||
|
foreach (string iface in managed_interfaces) {
|
||||||
|
if (Parent != null && Parent.Implements (iface))
|
||||||
|
continue;
|
||||||
|
sw.Write (", " + iface);
|
||||||
}
|
}
|
||||||
sw.WriteLine (" {");
|
sw.WriteLine (" {");
|
||||||
sw.WriteLine ();
|
sw.WriteLine ();
|
||||||
|
@ -155,7 +158,7 @@ namespace GtkSharp.Generation {
|
||||||
GenChildProperties (gen_info);
|
GenChildProperties (gen_info);
|
||||||
|
|
||||||
bool has_sigs = (sigs != null && sigs.Count > 0);
|
bool has_sigs = (sigs != null && sigs.Count > 0);
|
||||||
if (!has_sigs && interfaces != null) {
|
if (!has_sigs) {
|
||||||
foreach (string iface in interfaces) {
|
foreach (string iface in interfaces) {
|
||||||
ClassBase igen = table.GetClassGen (iface);
|
ClassBase igen = table.GetClassGen (iface);
|
||||||
if (igen != null && igen.Signals != null) {
|
if (igen != null && igen.Signals != null) {
|
||||||
|
@ -180,7 +183,7 @@ namespace GtkSharp.Generation {
|
||||||
|
|
||||||
GenMethods (gen_info, null, null);
|
GenMethods (gen_info, null, null);
|
||||||
|
|
||||||
if (interfaces != null) {
|
if (interfaces.Count != 0) {
|
||||||
Hashtable all_methods = new Hashtable ();
|
Hashtable all_methods = new Hashtable ();
|
||||||
Hashtable collisions = new Hashtable ();
|
Hashtable collisions = new Hashtable ();
|
||||||
foreach (string iface in interfaces) {
|
foreach (string iface in interfaces) {
|
||||||
|
|
|
@ -48,6 +48,30 @@ public Widget[] Children {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public IEnumerator GetEnumerator ()
|
||||||
|
{
|
||||||
|
IntPtr list_ptr = gtk_container_get_children (Handle);
|
||||||
|
GLib.List list = new GLib.List (list_ptr);
|
||||||
|
return list.GetEnumerator ();
|
||||||
|
}
|
||||||
|
|
||||||
|
class ChildAccumulator {
|
||||||
|
public ArrayList Children = new ArrayList ();
|
||||||
|
|
||||||
|
public void Add (Gtk.Widget widget)
|
||||||
|
{
|
||||||
|
Children.Add (widget);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public IEnumerable AllChildren {
|
||||||
|
get {
|
||||||
|
ChildAccumulator acc = new ChildAccumulator ();
|
||||||
|
Forall (new Gtk.Callback (acc.Add));
|
||||||
|
return acc.Children;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
[DllImport("libgtk-win32-2.0-0.dll")]
|
[DllImport("libgtk-win32-2.0-0.dll")]
|
||||||
static extern bool gtk_container_get_focus_chain (IntPtr raw, out IntPtr list_ptr);
|
static extern bool gtk_container_get_focus_chain (IntPtr raw, out IntPtr list_ptr);
|
||||||
|
|
||||||
|
@ -109,6 +133,7 @@ static extern void gtksharp_container_invoke_gtk_callback (IntPtr cb, IntPtr han
|
||||||
[GLib.CDeclCallback]
|
[GLib.CDeclCallback]
|
||||||
delegate void ForallDelegate (IntPtr container, bool include_internals, IntPtr cb, IntPtr data);
|
delegate void ForallDelegate (IntPtr container, bool include_internals, IntPtr cb, IntPtr data);
|
||||||
|
|
||||||
|
static ForallDelegate ForallOldCallback;
|
||||||
static ForallDelegate ForallCallback;
|
static ForallDelegate ForallCallback;
|
||||||
|
|
||||||
public struct CallbackInvoker {
|
public struct CallbackInvoker {
|
||||||
|
@ -139,13 +164,34 @@ public struct CallbackInvoker {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
static void Forall_cb (IntPtr container, bool include_internals, IntPtr cb, IntPtr data)
|
static void ForallOld_cb (IntPtr container, bool include_internals, IntPtr cb, IntPtr data)
|
||||||
{
|
{
|
||||||
Container obj = GLib.Object.GetObject (container, false) as Container;
|
Container obj = GLib.Object.GetObject (container, false) as Container;
|
||||||
CallbackInvoker invoker = new CallbackInvoker (cb, data);
|
CallbackInvoker invoker = new CallbackInvoker (cb, data);
|
||||||
obj.ForAll (include_internals, invoker);
|
obj.ForAll (include_internals, invoker);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void OverrideForallOld (GLib.GType gtype)
|
||||||
|
{
|
||||||
|
if (ForallOldCallback == null)
|
||||||
|
ForallOldCallback = new ForallDelegate (ForallOld_cb);
|
||||||
|
gtksharp_container_override_forall (gtype, ForallOldCallback);
|
||||||
|
}
|
||||||
|
|
||||||
|
[Obsolete ("Override the ForAll(bool,Gtk.Callback) method instead")]
|
||||||
|
[GLib.DefaultSignalHandler (Type=typeof(Gtk.Container), ConnectionMethod="OverrideForallOld")]
|
||||||
|
protected virtual void ForAll (bool include_internals, CallbackInvoker invoker)
|
||||||
|
{
|
||||||
|
gtksharp_container_base_forall (Handle, include_internals, invoker.Callback, invoker.Data);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void Forall_cb (IntPtr container, bool include_internals, IntPtr cb, IntPtr data)
|
||||||
|
{
|
||||||
|
Container obj = GLib.Object.GetObject (container, false) as Container;
|
||||||
|
CallbackInvoker invoker = new CallbackInvoker (cb, data);
|
||||||
|
obj.ForAll (include_internals, new Gtk.Callback (invoker.Invoke));
|
||||||
|
}
|
||||||
|
|
||||||
static void OverrideForall (GLib.GType gtype)
|
static void OverrideForall (GLib.GType gtype)
|
||||||
{
|
{
|
||||||
if (ForallCallback == null)
|
if (ForallCallback == null)
|
||||||
|
@ -154,8 +200,14 @@ static void OverrideForall (GLib.GType gtype)
|
||||||
}
|
}
|
||||||
|
|
||||||
[GLib.DefaultSignalHandler (Type=typeof(Gtk.Container), ConnectionMethod="OverrideForall")]
|
[GLib.DefaultSignalHandler (Type=typeof(Gtk.Container), ConnectionMethod="OverrideForall")]
|
||||||
protected virtual void ForAll (bool include_internals, CallbackInvoker invoker)
|
protected virtual void ForAll (bool include_internals, Gtk.Callback callback)
|
||||||
{
|
{
|
||||||
|
CallbackInvoker invoker;
|
||||||
|
try {
|
||||||
|
invoker = (CallbackInvoker)callback.Target;
|
||||||
|
} catch {
|
||||||
|
throw new ApplicationException ("ForAll can only be called as \"base.ForAll()\". Use Forall() or Foreach().");
|
||||||
|
}
|
||||||
gtksharp_container_base_forall (Handle, include_internals, invoker.Callback, invoker.Data);
|
gtksharp_container_base_forall (Handle, include_internals, invoker.Callback, invoker.Data);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -177,6 +177,7 @@
|
||||||
<attr path="/api/namespace/object[@cname='GtkColorSelection']/method[@name='SetPreviousColor']" name="hidden">1</attr>
|
<attr path="/api/namespace/object[@cname='GtkColorSelection']/method[@name='SetPreviousColor']" name="hidden">1</attr>
|
||||||
<attr path="/api/namespace/object[@cname='GtkCombo']/method[@name='SetPopdownStrings']" name="hidden">1</attr>
|
<attr path="/api/namespace/object[@cname='GtkCombo']/method[@name='SetPopdownStrings']" name="hidden">1</attr>
|
||||||
<attr path="/api/namespace/object[@cname='GtkComboBox']/method[@cname='gtk_combo_box_get_active_iter']/*/*[@type='GtkTreeIter*']" name="pass_as">out</attr>
|
<attr path="/api/namespace/object[@cname='GtkComboBox']/method[@cname='gtk_combo_box_get_active_iter']/*/*[@type='GtkTreeIter*']" name="pass_as">out</attr>
|
||||||
|
<add-node path="/api/namespace/object[@cname='GtkContainer']"><implements><interface name="IEnumerable" /></implements></add-node>
|
||||||
<attr path="/api/namespace/object[@cname='GtkContainer']/method[@name='ChildGetProperty']" name="hidden">1</attr>
|
<attr path="/api/namespace/object[@cname='GtkContainer']/method[@name='ChildGetProperty']" name="hidden">1</attr>
|
||||||
<attr path="/api/namespace/object[@cname='GtkContainer']/method[@name='Forall']/*/*[@name='callback']" name="scope">call</attr>
|
<attr path="/api/namespace/object[@cname='GtkContainer']/method[@name='Forall']/*/*[@name='callback']" name="scope">call</attr>
|
||||||
<attr path="/api/namespace/object[@cname='GtkContainer']/method[@name='Foreach']/*/*[@name='callback']" name="scope">call</attr>
|
<attr path="/api/namespace/object[@cname='GtkContainer']/method[@name='Foreach']/*/*[@name='callback']" name="scope">call</attr>
|
||||||
|
|
|
@ -1,642 +0,0 @@
|
||||||
using GLib;
|
|
||||||
using Gtk;
|
|
||||||
using System;
|
|
||||||
using System.Collections;
|
|
||||||
|
|
||||||
class CustomNotebookTest {
|
|
||||||
static CustomNotebook cn;
|
|
||||||
static Notebook nb;
|
|
||||||
static int tabCount;
|
|
||||||
|
|
||||||
public static int Main (string[] args)
|
|
||||||
{
|
|
||||||
Application.Init ();
|
|
||||||
Window win = new Window ("Custom Notebook Test");
|
|
||||||
win.DeleteEvent += new DeleteEventHandler (OnQuit);
|
|
||||||
|
|
||||||
VBox box = new VBox (false, 5);
|
|
||||||
Button addButton = new Button ("Add Tab");
|
|
||||||
//addButton.Clicked += OnAddTab;
|
|
||||||
Button rmButton = new Button ("Remove Tab");
|
|
||||||
rmButton.Clicked += OnRemoveTab;
|
|
||||||
box.PackStart (addButton, false, false, 0);
|
|
||||||
box.PackStart (rmButton, false, false, 0);
|
|
||||||
HPaned paned = new HPaned ();
|
|
||||||
|
|
||||||
cn = new CustomNotebook ();
|
|
||||||
cn.BorderWidth = 5;
|
|
||||||
cn.Scrollable = false;
|
|
||||||
Gdk.Pixbuf icon = cn.RenderIcon (Stock.Execute, IconSize.Menu, "");
|
|
||||||
//for (tabCount = 0; tabCount < 3; tabCount++)
|
|
||||||
cn.AppendPage (new Label ("Custom Notebook"), Stock.Execute, "extended tab" + tabCount);
|
|
||||||
cn.AppendPage (new Label ("Custom Notebook"), Stock.Execute, "tab" + (tabCount + 1));
|
|
||||||
cn.AppendPage (new Label ("Custom Notebook"), Stock.Execute, "extended tab" + (tabCount + 2));
|
|
||||||
paned.Pack1 (cn, true, false);
|
|
||||||
|
|
||||||
nb = new Notebook ();
|
|
||||||
nb.BorderWidth = 5;
|
|
||||||
nb.Scrollable = false;
|
|
||||||
for (tabCount = 0; tabCount < 3; tabCount++)
|
|
||||||
nb.AppendPage (new Label ("Regular Notebook"), new Label ("tab" + tabCount));
|
|
||||||
paned.Pack2 (nb, true, false);
|
|
||||||
box.PackEnd (paned, true, true, 0);
|
|
||||||
|
|
||||||
win.Add (box);
|
|
||||||
win.ShowAll ();
|
|
||||||
Application.Run ();
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
/*static void OnAddTab (object sender, EventArgs args)
|
|
||||||
{
|
|
||||||
cn.AppendPage (new Label ("Custom Notebook"), Stock.Execute, "tab" + tabCount + 1);
|
|
||||||
cn.ShowAll ();
|
|
||||||
nb.AppendPage (new Label ("Regular Notebook"), new Label ("tab" + tabCount + 1));
|
|
||||||
nb.ShowAll ();
|
|
||||||
tabCount++;
|
|
||||||
}*/
|
|
||||||
|
|
||||||
static void OnRemoveTab (object sender, EventArgs args)
|
|
||||||
{
|
|
||||||
}
|
|
||||||
|
|
||||||
static void OnQuit (object sender, DeleteEventArgs args)
|
|
||||||
{
|
|
||||||
Application.Quit ();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
class CustomNotebookPage {
|
|
||||||
private Gdk.Rectangle allocation;
|
|
||||||
private Widget child = null;
|
|
||||||
private Gdk.Pixbuf icon = null;
|
|
||||||
private bool ellipsize = false;
|
|
||||||
private string label = null;
|
|
||||||
private Pango.Layout layout = null;
|
|
||||||
private int layoutWidth = -1;
|
|
||||||
private int layoutHeight = -1;
|
|
||||||
private Requisition requisition;
|
|
||||||
private string stockid = null;
|
|
||||||
|
|
||||||
public Gdk.Rectangle Allocation {
|
|
||||||
get {
|
|
||||||
return allocation;
|
|
||||||
}
|
|
||||||
set {
|
|
||||||
allocation = value;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public Widget Child {
|
|
||||||
get {
|
|
||||||
return child;
|
|
||||||
}
|
|
||||||
set {
|
|
||||||
child = value;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public bool Ellipsize {
|
|
||||||
get {
|
|
||||||
return ellipsize;
|
|
||||||
}
|
|
||||||
set {
|
|
||||||
ellipsize = value;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public Gdk.Pixbuf Icon {
|
|
||||||
get {
|
|
||||||
if (icon == null && StockId != null) {
|
|
||||||
icon = child.RenderIcon (StockId, IconSize.Menu, "");
|
|
||||||
}
|
|
||||||
|
|
||||||
return icon;
|
|
||||||
}
|
|
||||||
set {
|
|
||||||
icon = value;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public string Label {
|
|
||||||
get {
|
|
||||||
return label;
|
|
||||||
}
|
|
||||||
set {
|
|
||||||
label = value;
|
|
||||||
layout = null;
|
|
||||||
layoutWidth = -1;
|
|
||||||
layoutHeight = -1;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public Pango.Layout Layout {
|
|
||||||
get {
|
|
||||||
if (layout == null && Label != null) {
|
|
||||||
layout = child.CreatePangoLayout (label);
|
|
||||||
layout.GetPixelSize (out layoutWidth, out layoutHeight);
|
|
||||||
}
|
|
||||||
|
|
||||||
return layout;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public int LayoutWidth {
|
|
||||||
get {
|
|
||||||
if (Layout != null)
|
|
||||||
return layoutWidth;
|
|
||||||
else
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public int LayoutHeight {
|
|
||||||
get {
|
|
||||||
if (Layout != null)
|
|
||||||
return layoutHeight;
|
|
||||||
else
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public Requisition Requisition {
|
|
||||||
get {
|
|
||||||
return requisition;
|
|
||||||
}
|
|
||||||
set {
|
|
||||||
requisition = value;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public string StockId {
|
|
||||||
get {
|
|
||||||
return stockid;
|
|
||||||
}
|
|
||||||
set {
|
|
||||||
stockid = value;
|
|
||||||
icon = null;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public CustomNotebookPage (Widget child, string label)
|
|
||||||
{
|
|
||||||
Child = child;
|
|
||||||
Label = label;
|
|
||||||
}
|
|
||||||
|
|
||||||
public CustomNotebookPage (Widget child, Gdk.Pixbuf icon, string label)
|
|
||||||
{
|
|
||||||
Child = child;
|
|
||||||
Icon = icon;
|
|
||||||
Label = label;
|
|
||||||
}
|
|
||||||
|
|
||||||
public CustomNotebookPage (Widget child, string stockid, string label)
|
|
||||||
{
|
|
||||||
Child = child;
|
|
||||||
Label = label;
|
|
||||||
StockId = stockid;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
class CustomNotebook : Container {
|
|
||||||
private readonly int tabCurvature = 1;
|
|
||||||
private readonly int tabOverlap = 2;
|
|
||||||
private ArrayList pages = new ArrayList ();
|
|
||||||
private bool closable;
|
|
||||||
private bool scrollable;
|
|
||||||
private PositionType tabPosition;
|
|
||||||
private int tabHBorder;
|
|
||||||
private int tabVBorder;
|
|
||||||
|
|
||||||
public bool Closable {
|
|
||||||
get {
|
|
||||||
return closable;
|
|
||||||
}
|
|
||||||
set {
|
|
||||||
closable = value;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private CustomNotebookPage CurrentPage {
|
|
||||||
get {
|
|
||||||
return (CustomNotebookPage)pages[0];
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public bool Scrollable {
|
|
||||||
get {
|
|
||||||
return scrollable;
|
|
||||||
}
|
|
||||||
set {
|
|
||||||
scrollable = value;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public Gtk.PositionType TabPosition {
|
|
||||||
get {
|
|
||||||
return tabPosition;
|
|
||||||
}
|
|
||||||
set {
|
|
||||||
switch (value) {
|
|
||||||
case PositionType.Left:
|
|
||||||
case PositionType.Right:
|
|
||||||
Console.WriteLine ("PositionType.Left or Right is not supported by this widget");
|
|
||||||
break;
|
|
||||||
default:
|
|
||||||
tabPosition = value;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/*static CustomNotebook ()
|
|
||||||
{
|
|
||||||
Container.OverrideForall (CustomNotebook.GType);
|
|
||||||
}*/
|
|
||||||
|
|
||||||
public CustomNotebook () : base ()
|
|
||||||
{
|
|
||||||
closable = true;
|
|
||||||
scrollable = false;
|
|
||||||
tabPosition = PositionType.Top;
|
|
||||||
tabHBorder = 2;
|
|
||||||
tabVBorder = 2;
|
|
||||||
|
|
||||||
WidgetFlags |= WidgetFlags.NoWindow;
|
|
||||||
}
|
|
||||||
|
|
||||||
public void AppendPage (Widget child, string label)
|
|
||||||
{
|
|
||||||
pages.Add (new CustomNotebookPage (child, label));
|
|
||||||
child.Parent = this;
|
|
||||||
}
|
|
||||||
|
|
||||||
public void AppendPage (Widget child, string stockid, string label)
|
|
||||||
{
|
|
||||||
pages.Add (new CustomNotebookPage (child, stockid, label));
|
|
||||||
child.Parent = this;
|
|
||||||
}
|
|
||||||
|
|
||||||
public void AppendPage (Widget child, Gdk.Pixbuf icon, string label)
|
|
||||||
{
|
|
||||||
pages.Add (new CustomNotebookPage (child, icon, label));
|
|
||||||
child.Parent = this;
|
|
||||||
}
|
|
||||||
|
|
||||||
private void EllipsizeLayout (Pango.Layout layout, int width)
|
|
||||||
{
|
|
||||||
if (width <= 0) {
|
|
||||||
layout.SetText ("");
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
int layoutWidth, layoutHeight;
|
|
||||||
layout.GetPixelSize (out layoutWidth, out layoutHeight);
|
|
||||||
if (layoutWidth <= width)
|
|
||||||
return;
|
|
||||||
|
|
||||||
// Calculate ellipsis width.
|
|
||||||
Pango.Layout ell = layout.Copy ();
|
|
||||||
ell.SetText ("...");
|
|
||||||
int ellWidth, ellHeight;
|
|
||||||
ell.GetPixelSize (out ellWidth, out ellHeight);
|
|
||||||
|
|
||||||
if (width < ellWidth) {
|
|
||||||
// Not even ellipsis fits, so hide text.
|
|
||||||
layout.SetText ("");
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Shrink total available width by the width of the ellipsis.
|
|
||||||
width -= ellWidth;
|
|
||||||
string text = layout.Text;
|
|
||||||
Console.WriteLine ("layout text = {0}", text);
|
|
||||||
Console.WriteLine ("line count: {0}", layout.LineCount);
|
|
||||||
Pango.LayoutLine line = layout.Lines[0];
|
|
||||||
//Console.WriteLine ("layout = {0}", line.layout.Text);
|
|
||||||
//Console.WriteLine ("line = {0}", line.Length);
|
|
||||||
int idx = 0, trailing = 0;
|
|
||||||
if (line.XToIndex (width * 1024, out idx, out trailing)) {
|
|
||||||
text = text.Substring (0, idx - 1);
|
|
||||||
text += "...";
|
|
||||||
layout.SetText (text);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
protected override bool OnExposeEvent (Gdk.EventExpose args)
|
|
||||||
{
|
|
||||||
int x, y, width, height, gapX, gapWidth;
|
|
||||||
int bw = (int)BorderWidth;
|
|
||||||
|
|
||||||
x = Allocation.X + bw;
|
|
||||||
y = Allocation.Y + bw;
|
|
||||||
width = Allocation.Width - 2 * bw;
|
|
||||||
height = Allocation.Height - 2 * bw;
|
|
||||||
|
|
||||||
switch (TabPosition) {
|
|
||||||
case PositionType.Top:
|
|
||||||
y += CurrentPage.Allocation.Height;
|
|
||||||
height -= CurrentPage.Allocation.Height;
|
|
||||||
break;
|
|
||||||
case PositionType.Bottom:
|
|
||||||
height -= CurrentPage.Allocation.Height;
|
|
||||||
break;
|
|
||||||
case PositionType.Left:
|
|
||||||
case PositionType.Right:
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
gapX = gapWidth = 0;
|
|
||||||
switch (TabPosition) {
|
|
||||||
case PositionType.Top:
|
|
||||||
case PositionType.Bottom:
|
|
||||||
gapX = CurrentPage.Allocation.X - Allocation.X - bw;
|
|
||||||
gapWidth = CurrentPage.Allocation.Width;
|
|
||||||
break;
|
|
||||||
case PositionType.Left:
|
|
||||||
case PositionType.Right:
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
Style.PaintBoxGap (Style, GdkWindow, StateType.Normal,
|
|
||||||
ShadowType.Out, args.Area, this,
|
|
||||||
"notebook", x, y, width, height,
|
|
||||||
TabPosition, gapX, gapWidth);
|
|
||||||
|
|
||||||
for (int i = pages.Count - 1; i >= 0; i--) {
|
|
||||||
CustomNotebookPage page = (CustomNotebookPage)pages[i];
|
|
||||||
Gdk.Rectangle pageAlloc = page.Allocation;
|
|
||||||
|
|
||||||
StateType state = page == CurrentPage ? StateType.Normal : StateType.Active;
|
|
||||||
Style.PaintExtension (Style, GdkWindow, state,
|
|
||||||
ShadowType.Out, args.Area, this,
|
|
||||||
"tab", pageAlloc.X, pageAlloc.Y,
|
|
||||||
pageAlloc.Width, pageAlloc.Height,
|
|
||||||
PositionType.Bottom);
|
|
||||||
|
|
||||||
// FIXME: Only add YThickness when TabPosition = Top;
|
|
||||||
y = pageAlloc.Y + Style.YThickness + FocusLineWidth + tabVBorder;
|
|
||||||
height = pageAlloc.Height - Style.YThickness - 2 * (tabVBorder + FocusLineWidth);
|
|
||||||
if (page.Icon != null) {
|
|
||||||
x = pageAlloc.X + (pageAlloc.Width + 1 -
|
|
||||||
page.Icon.Width -
|
|
||||||
page.LayoutWidth) / 2;
|
|
||||||
int iconY = y + (height - page.Icon.Height) / 2;
|
|
||||||
|
|
||||||
GdkWindow.DrawPixbuf (Style.BackgroundGC (State),
|
|
||||||
page.Icon, 0, 0, x, iconY,
|
|
||||||
page.Icon.Width,
|
|
||||||
page.Icon.Height,
|
|
||||||
Gdk.RgbDither.None, 0, 0);
|
|
||||||
x += page.Icon.Width + 1;
|
|
||||||
} else {
|
|
||||||
x = pageAlloc.X + (pageAlloc.Width - page.LayoutWidth) / 2;
|
|
||||||
}
|
|
||||||
|
|
||||||
y += (height - page.LayoutHeight) / 2;
|
|
||||||
if (page.Ellipsize) {
|
|
||||||
width = pageAlloc.Width - (page.Icon.Width + 1);
|
|
||||||
Pango.Layout layout = page.Layout;
|
|
||||||
EllipsizeLayout (layout, width);
|
|
||||||
Console.WriteLine ("ellLayout = {0}", layout.Text);
|
|
||||||
Style.PaintLayout (Style, GdkWindow, State,
|
|
||||||
true, args.Area, this, null,
|
|
||||||
x, y, layout);
|
|
||||||
} else {
|
|
||||||
Style.PaintLayout (Style, GdkWindow, State,
|
|
||||||
true, args.Area, this, null,
|
|
||||||
x, y, page.Layout);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return base.OnExposeEvent (args);
|
|
||||||
}
|
|
||||||
|
|
||||||
protected override void ForAll (bool include_internals, CallbackInvoker invoker)
|
|
||||||
{
|
|
||||||
foreach (CustomNotebookPage page in pages) {
|
|
||||||
invoker.Invoke (page.Child);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
protected override void OnRealized ()
|
|
||||||
{
|
|
||||||
WidgetFlags |= WidgetFlags.Realized;
|
|
||||||
|
|
||||||
GdkWindow = ParentWindow;
|
|
||||||
Style = Style.Attach (GdkWindow);
|
|
||||||
}
|
|
||||||
|
|
||||||
protected override void OnSizeAllocated (Gdk.Rectangle allocation)
|
|
||||||
{
|
|
||||||
base.OnSizeAllocated (allocation);
|
|
||||||
|
|
||||||
if (pages.Count == 0)
|
|
||||||
return;
|
|
||||||
|
|
||||||
int bw = (int)BorderWidth;
|
|
||||||
|
|
||||||
Gdk.Rectangle childAlloc;
|
|
||||||
childAlloc.X = allocation.X + bw + Style.XThickness;
|
|
||||||
childAlloc.Y = allocation.Y + bw + Style.YThickness;
|
|
||||||
childAlloc.Width = Math.Max (1, allocation.Width - 2 * bw -
|
|
||||||
2 * Style.XThickness);
|
|
||||||
childAlloc.Height = Math.Max (1, allocation.Height - 2 * bw -
|
|
||||||
2 * Style.YThickness);
|
|
||||||
|
|
||||||
switch (TabPosition) {
|
|
||||||
case PositionType.Top:
|
|
||||||
childAlloc.Y += CurrentPage.Requisition.Height;
|
|
||||||
childAlloc.Height = Math.Max (1, childAlloc.Height -
|
|
||||||
CurrentPage.Requisition.Height);
|
|
||||||
break;
|
|
||||||
case PositionType.Bottom:
|
|
||||||
childAlloc.Height = Math.Max (1, childAlloc.Height -
|
|
||||||
CurrentPage.Requisition.Height);
|
|
||||||
break;
|
|
||||||
case PositionType.Left:
|
|
||||||
case PositionType.Right:
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
foreach (CustomNotebookPage page in pages) {
|
|
||||||
page.Child.SizeAllocate (childAlloc);
|
|
||||||
}
|
|
||||||
|
|
||||||
// gtk_notebook_pages_allocate.
|
|
||||||
childAlloc.X = allocation.X + bw;
|
|
||||||
childAlloc.Y = allocation.Y + bw;
|
|
||||||
|
|
||||||
switch (TabPosition) {
|
|
||||||
case PositionType.Top:
|
|
||||||
childAlloc.Height = CurrentPage.Requisition.Height;
|
|
||||||
break;
|
|
||||||
case PositionType.Bottom:
|
|
||||||
childAlloc.Y = (allocation.Y + allocation.Height -
|
|
||||||
CurrentPage.Requisition.Height - bw);
|
|
||||||
childAlloc.Height = CurrentPage.Requisition.Height;
|
|
||||||
break;
|
|
||||||
case PositionType.Left:
|
|
||||||
case PositionType.Right:
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
bool ellipsize = false;
|
|
||||||
int avgWidth = 0;
|
|
||||||
int tabX = childAlloc.X;
|
|
||||||
if (!scrollable) {
|
|
||||||
int tabWidth = 0;
|
|
||||||
foreach (CustomNotebookPage page in pages) {
|
|
||||||
tabWidth += page.Requisition.Width;
|
|
||||||
}
|
|
||||||
|
|
||||||
Console.WriteLine ("total tabwidth: {0}", tabWidth);
|
|
||||||
Console.WriteLine ("allocated width: {0}", childAlloc.Width);
|
|
||||||
|
|
||||||
if (tabWidth > childAlloc.Width) {
|
|
||||||
ellipsize = true;
|
|
||||||
avgWidth = childAlloc.Width / pages.Count;
|
|
||||||
tabWidth = childAlloc.Width;
|
|
||||||
Console.WriteLine ("average tabwidth: {0}", avgWidth);
|
|
||||||
|
|
||||||
int count = pages.Count;
|
|
||||||
foreach (CustomNotebookPage page in pages) {
|
|
||||||
if (page.Requisition.Width <= avgWidth) {
|
|
||||||
count--;
|
|
||||||
tabWidth -= page.Requisition.Width;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
Console.WriteLine ("number of pages exceeding that: {0}", count);
|
|
||||||
Console.WriteLine ("space per page available: {0}", tabWidth / count);
|
|
||||||
|
|
||||||
// FIXME: check for TabPosition.
|
|
||||||
int maxWidth = tabWidth / count;
|
|
||||||
foreach (CustomNotebookPage page in pages) {
|
|
||||||
Gdk.Rectangle pageAlloc = page.Allocation;
|
|
||||||
pageAlloc.X = tabX;
|
|
||||||
pageAlloc.Y = childAlloc.Y;
|
|
||||||
|
|
||||||
if (page.Requisition.Width > maxWidth) {
|
|
||||||
pageAlloc.Width = maxWidth + tabOverlap;
|
|
||||||
page.Ellipsize = true;
|
|
||||||
} else {
|
|
||||||
pageAlloc.Width = page.Requisition.Width + tabOverlap;
|
|
||||||
}
|
|
||||||
|
|
||||||
pageAlloc.Height = childAlloc.Height;
|
|
||||||
tabX += pageAlloc.Width - tabOverlap;
|
|
||||||
|
|
||||||
if (page != CurrentPage) {
|
|
||||||
pageAlloc.Y += Style.YThickness;
|
|
||||||
pageAlloc.Height -= Style.YThickness;
|
|
||||||
}
|
|
||||||
|
|
||||||
page.Allocation = pageAlloc;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
switch (TabPosition) {
|
|
||||||
case PositionType.Top:
|
|
||||||
case PositionType.Bottom:
|
|
||||||
foreach (CustomNotebookPage page in pages) {
|
|
||||||
Gdk.Rectangle pageAlloc = page.Allocation;
|
|
||||||
pageAlloc.X = tabX;
|
|
||||||
pageAlloc.Y = childAlloc.Y;
|
|
||||||
pageAlloc.Width = page.Requisition.Width + tabOverlap;
|
|
||||||
pageAlloc.Height = childAlloc.Height;
|
|
||||||
tabX += pageAlloc.Width - tabOverlap;
|
|
||||||
|
|
||||||
if (page != CurrentPage) {
|
|
||||||
pageAlloc.Y += Style.YThickness;
|
|
||||||
pageAlloc.Height -= Style.YThickness;
|
|
||||||
}
|
|
||||||
|
|
||||||
page.Allocation = pageAlloc;
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
case PositionType.Left:
|
|
||||||
case PositionType.Right:
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
protected override void OnSizeRequested (ref Requisition requisition)
|
|
||||||
{
|
|
||||||
requisition.Width = requisition.Height = 0;
|
|
||||||
|
|
||||||
foreach (CustomNotebookPage page in pages) {
|
|
||||||
if (!page.Child.Visible)
|
|
||||||
continue;
|
|
||||||
|
|
||||||
Requisition childReq = page.Child.SizeRequest ();
|
|
||||||
requisition.Width = Math.Max (requisition.Width, childReq.Width);
|
|
||||||
requisition.Height = Math.Max (requisition.Height, childReq.Height);
|
|
||||||
}
|
|
||||||
|
|
||||||
requisition.Width += 2 * Style.XThickness;
|
|
||||||
requisition.Height += 2 * Style.YThickness;
|
|
||||||
|
|
||||||
int tabWidth = 0;
|
|
||||||
int tabHeight = 0;
|
|
||||||
int tabMax = 0;
|
|
||||||
int padding;
|
|
||||||
foreach (CustomNotebookPage page in pages) {
|
|
||||||
Requisition pageReq;
|
|
||||||
if (page.Icon != null) {
|
|
||||||
pageReq.Width = page.Icon.Width + page.LayoutWidth +
|
|
||||||
Style.XThickness * 2;
|
|
||||||
pageReq.Height = Math.Max (page.Icon.Height, page.LayoutHeight) +
|
|
||||||
Style.YThickness * 2;
|
|
||||||
} else {
|
|
||||||
pageReq.Width = page.LayoutWidth + Style.XThickness * 2;
|
|
||||||
pageReq.Height = page.LayoutHeight + Style.YThickness * 2;
|
|
||||||
}
|
|
||||||
|
|
||||||
switch (TabPosition) {
|
|
||||||
case PositionType.Top:
|
|
||||||
case PositionType.Bottom:
|
|
||||||
pageReq.Height += (tabVBorder + FocusLineWidth) * 2;
|
|
||||||
tabHeight = Math.Max (tabHeight, pageReq.Height);
|
|
||||||
tabMax = Math.Max (tabMax, pageReq.Width);
|
|
||||||
break;
|
|
||||||
case PositionType.Left:
|
|
||||||
case PositionType.Right:
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
page.Requisition = pageReq;
|
|
||||||
}
|
|
||||||
|
|
||||||
switch (TabPosition) {
|
|
||||||
case PositionType.Top:
|
|
||||||
case PositionType.Bottom:
|
|
||||||
padding = 2 * (tabCurvature + FocusLineWidth
|
|
||||||
+ tabHBorder) - tabOverlap;
|
|
||||||
tabMax += padding;
|
|
||||||
|
|
||||||
Requisition pageReq;
|
|
||||||
foreach (CustomNotebookPage page in pages) {
|
|
||||||
pageReq = page.Requisition;
|
|
||||||
pageReq.Width += padding;
|
|
||||||
tabWidth += pageReq.Width;
|
|
||||||
pageReq.Height = tabHeight;
|
|
||||||
page.Requisition = pageReq;
|
|
||||||
}
|
|
||||||
|
|
||||||
/*if (!Scrollable)
|
|
||||||
requisition.Width = Math.Max (requisition.Width,
|
|
||||||
tabWidth + tabOverlap);*/
|
|
||||||
requisition.Height += tabHeight;
|
|
||||||
break;
|
|
||||||
case PositionType.Left:
|
|
||||||
case PositionType.Right:
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
requisition.Width += (int)BorderWidth * 2;
|
|
||||||
requisition.Height += (int)BorderWidth * 2;
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -122,8 +122,7 @@ namespace GtkDemo
|
||||||
{
|
{
|
||||||
ToggleButton toggle = o as ToggleButton;
|
ToggleButton toggle = o as ToggleButton;
|
||||||
|
|
||||||
Widget[] children = vbox.Children;
|
foreach (Widget widget in vbox) {
|
||||||
foreach (Widget widget in children) {
|
|
||||||
// don't disable our toggle
|
// don't disable our toggle
|
||||||
if (widget != toggle)
|
if (widget != toggle)
|
||||||
widget.Sensitive = !toggle.Active;
|
widget.Sensitive = !toggle.Active;
|
||||||
|
|
|
@ -40,7 +40,7 @@ DOTNET_TARGETS=
|
||||||
DOTNET_ASSEMBLY=
|
DOTNET_ASSEMBLY=
|
||||||
endif
|
endif
|
||||||
|
|
||||||
TARGETS = custom-notebook.exe custom-widget.exe custom-cellrenderer.exe gtk-hello-world.exe button.exe calendar.exe subclass.exe menu.exe size.exe scribble.exe scribble-xinput.exe treeviewdemo.exe managedtreeviewdemo.exe nodeviewdemo.exe testdnd.exe actions.exe $(GNOMEVFS_TARGETS) $(GNOME_TARGETS) $(GLADE_TARGETS) $(VTE_TARGETS) $(DOTNET_TARGETS)
|
TARGETS = polarfixed.exe custom-widget.exe custom-cellrenderer.exe gtk-hello-world.exe button.exe calendar.exe subclass.exe menu.exe size.exe scribble.exe scribble-xinput.exe treeviewdemo.exe managedtreeviewdemo.exe nodeviewdemo.exe testdnd.exe actions.exe $(GNOMEVFS_TARGETS) $(GNOME_TARGETS) $(GLADE_TARGETS) $(VTE_TARGETS) $(DOTNET_TARGETS)
|
||||||
|
|
||||||
DEBUGS = $(addsuffix .mdb, $(TARGETS))
|
DEBUGS = $(addsuffix .mdb, $(TARGETS))
|
||||||
|
|
||||||
|
@ -124,8 +124,8 @@ custom-widget.exe: $(srcdir)/CustomWidget.cs $(assemblies)
|
||||||
actions.exe: $(srcdir)/Actions.cs
|
actions.exe: $(srcdir)/Actions.cs
|
||||||
$(CSC) /debug /unsafe /out:actions.exe $(references) $(srcdir)/Actions.cs
|
$(CSC) /debug /unsafe /out:actions.exe $(references) $(srcdir)/Actions.cs
|
||||||
|
|
||||||
custom-notebook.exe: $(srcdir)/CustomNotebook.cs $(assemblies)
|
polarfixed.exe: $(srcdir)/PolarFixed.cs $(assemblies)
|
||||||
$(CSC) /debug /out:custom-notebook.exe $(references) $(srcdir)/CustomNotebook.cs
|
$(CSC) /debug /out:polarfixed.exe $(references) $(srcdir)/PolarFixed.cs
|
||||||
|
|
||||||
testvfs.exe: $(srcdir)/TestVfs.cs $(assemblies)
|
testvfs.exe: $(srcdir)/TestVfs.cs $(assemblies)
|
||||||
$(CSC) /debug /out:testvfs.exe $(references) $(srcdir)/TestVfs.cs
|
$(CSC) /debug /out:testvfs.exe $(references) $(srcdir)/TestVfs.cs
|
||||||
|
|
236
sample/PolarFixed.cs
Normal file
236
sample/PolarFixed.cs
Normal file
|
@ -0,0 +1,236 @@
|
||||||
|
// This is a completely pointless widget, but it shows how to subclass container...
|
||||||
|
|
||||||
|
using System;
|
||||||
|
using System.Collections;
|
||||||
|
using Gtk;
|
||||||
|
using Gdk;
|
||||||
|
|
||||||
|
class PolarFixed : Container {
|
||||||
|
ArrayList children;
|
||||||
|
|
||||||
|
public PolarFixed ()
|
||||||
|
{
|
||||||
|
children = new ArrayList ();
|
||||||
|
WidgetFlags |= WidgetFlags.NoWindow;
|
||||||
|
}
|
||||||
|
|
||||||
|
// The child properties object
|
||||||
|
public class PolarFixedChild : ContainerChild {
|
||||||
|
double theta;
|
||||||
|
uint r;
|
||||||
|
|
||||||
|
public PolarFixedChild (PolarFixed parent, Widget child, double theta, uint r) : base (parent, child)
|
||||||
|
{
|
||||||
|
this.theta = theta;
|
||||||
|
this.r = r;
|
||||||
|
}
|
||||||
|
|
||||||
|
// We call parent.QueueResize() from the property setters here so that you
|
||||||
|
// can move the widget around just by changing its child properties (just
|
||||||
|
// like with a native container class).
|
||||||
|
|
||||||
|
public double Theta {
|
||||||
|
get { return theta; }
|
||||||
|
set {
|
||||||
|
theta = value;
|
||||||
|
parent.QueueResize ();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public uint R {
|
||||||
|
get { return r; }
|
||||||
|
set {
|
||||||
|
r = value;
|
||||||
|
parent.QueueResize ();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Override the child properties accessor to return the right object from
|
||||||
|
// "children".
|
||||||
|
public override ContainerChild this [Widget w] {
|
||||||
|
get {
|
||||||
|
foreach (PolarFixedChild pfc in children) {
|
||||||
|
if (pfc.Child == w)
|
||||||
|
return pfc;
|
||||||
|
}
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Indicate the kind of children the container will accept. Most containers
|
||||||
|
// will accept any kind of child, so they should return Gtk.Widget.GType.
|
||||||
|
// The default is "GLib.GType.None", which technically means that no (new)
|
||||||
|
// children can be added to the container, though Container.Add does not
|
||||||
|
// enforce this.
|
||||||
|
public override GLib.GType ChildType ()
|
||||||
|
{
|
||||||
|
return Gtk.Widget.GType;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Implement gtk_container_forall(), which is also used by
|
||||||
|
// Gtk.Container.Children and Gtk.Container.AllChildren.
|
||||||
|
protected override void ForAll (bool include_internals, Callback callback)
|
||||||
|
{
|
||||||
|
foreach (PolarFixedChild pfc in children)
|
||||||
|
callback (pfc.Child);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Invoked by Container.Add (w). It's good practice to have this do *something*,
|
||||||
|
// even if it's not something terribly useful.
|
||||||
|
protected override void OnAdded (Widget w)
|
||||||
|
{
|
||||||
|
Put (w, 0.0, 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
// our own adder method
|
||||||
|
public void Put (Widget w, double theta, uint r)
|
||||||
|
{
|
||||||
|
children.Add (new PolarFixedChild (this, w, theta, r));
|
||||||
|
w.Parent = this;
|
||||||
|
QueueResize ();
|
||||||
|
}
|
||||||
|
|
||||||
|
public void Move (Widget w, double theta, uint r)
|
||||||
|
{
|
||||||
|
PolarFixedChild pfc = (PolarFixedChild)this[w];
|
||||||
|
if (pfc != null) {
|
||||||
|
pfc.Theta = theta;
|
||||||
|
pfc.R = r;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// invoked by Container.Remove (w)
|
||||||
|
protected override void OnRemoved (Widget w)
|
||||||
|
{
|
||||||
|
PolarFixedChild pfc = (PolarFixedChild)this[w];
|
||||||
|
if (pfc != null) {
|
||||||
|
pfc.Child.Unparent ();
|
||||||
|
children.Remove (pfc);
|
||||||
|
QueueResize ();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Handle size request
|
||||||
|
protected override void OnSizeRequested (ref Requisition req)
|
||||||
|
{
|
||||||
|
Requisition childReq;
|
||||||
|
int x, y;
|
||||||
|
|
||||||
|
req.Width = req.Height = 0;
|
||||||
|
foreach (PolarFixedChild pfc in children) {
|
||||||
|
// Recursively SizeRequest each child
|
||||||
|
childReq = pfc.Child.SizeRequest ();
|
||||||
|
|
||||||
|
// Figure out where we're going to put it
|
||||||
|
x = (int)(Math.Cos (pfc.Theta) * pfc.R) + childReq.Width / 2;
|
||||||
|
y = (int)(Math.Sin (pfc.Theta) * pfc.R) + childReq.Height / 2;
|
||||||
|
|
||||||
|
// Update our own size request to fit it
|
||||||
|
if (req.Width < 2 * x)
|
||||||
|
req.Width = 2 * x;
|
||||||
|
if (req.Height < 2 * y)
|
||||||
|
req.Height = 2 * y;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Take Container.BorderWidth into account
|
||||||
|
req.Width += (int)(2 * BorderWidth);
|
||||||
|
req.Height += (int)(2 * BorderWidth);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Size allocation. Note that the allocation received may be smaller than what we
|
||||||
|
// requested. Some containers will take that into account by giving some or all
|
||||||
|
// of their children a smaller allocation than they requested. Other containers
|
||||||
|
// (like this one) just let their children get placed partly out-of-bounds if they
|
||||||
|
// aren't allocated enough room.
|
||||||
|
protected override void OnSizeAllocated (Rectangle allocation)
|
||||||
|
{
|
||||||
|
Requisition childReq;
|
||||||
|
int cx, cy, x, y;
|
||||||
|
|
||||||
|
// This sets the "Allocation" property. For widgets that
|
||||||
|
// have a GdkWindow, it also calls GdkWindow.MoveResize()
|
||||||
|
base.OnSizeAllocated (allocation);
|
||||||
|
|
||||||
|
// Figure out where the center of the grid will be
|
||||||
|
cx = allocation.X + (allocation.Width / 2);
|
||||||
|
cy = allocation.Y + (allocation.Height / 2);
|
||||||
|
|
||||||
|
foreach (PolarFixedChild pfc in children) {
|
||||||
|
// Use ChildRequisition rather than SizeRequest(),
|
||||||
|
// to ask for "what this child requested in the
|
||||||
|
// last SizeRequest", rather than having it
|
||||||
|
// compute it anew.
|
||||||
|
childReq = pfc.Child.ChildRequisition;
|
||||||
|
|
||||||
|
x = (int)(Math.Cos (pfc.Theta) * pfc.R) - childReq.Width / 2;
|
||||||
|
y = (int)(Math.Sin (pfc.Theta) * pfc.R) + childReq.Height / 2;
|
||||||
|
|
||||||
|
allocation.X = cx + x;
|
||||||
|
allocation.Width = childReq.Width;
|
||||||
|
allocation.Y = cy - y;
|
||||||
|
allocation.Height = childReq.Height;
|
||||||
|
|
||||||
|
pfc.Child.Allocation = allocation;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
class Test {
|
||||||
|
public static void Main ()
|
||||||
|
{
|
||||||
|
uint r;
|
||||||
|
double theta;
|
||||||
|
|
||||||
|
Application.Init ();
|
||||||
|
|
||||||
|
Gtk.Window win = new Gtk.Window ("Polar Coordinate Container");
|
||||||
|
win.DeleteEvent += Window_Delete;
|
||||||
|
|
||||||
|
Notebook notebook = new Notebook ();
|
||||||
|
win.Add (notebook);
|
||||||
|
|
||||||
|
// Clock
|
||||||
|
PolarFixed pf = new PolarFixed ();
|
||||||
|
notebook.AppendPage (pf, new Label ("Clock"));
|
||||||
|
|
||||||
|
for (int hour = 1; hour <= 12; hour ++) {
|
||||||
|
theta = (Math.PI / 2) - hour * (Math.PI / 6);
|
||||||
|
if (theta < 0)
|
||||||
|
theta += 2 * Math.PI;
|
||||||
|
|
||||||
|
Label l = new Label ("<big><b>" + hour.ToString () + "</b></big>");
|
||||||
|
l.UseMarkup = true;
|
||||||
|
pf.Put (l, theta, 200);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Spiral
|
||||||
|
pf = new PolarFixed ();
|
||||||
|
notebook.AppendPage (pf, new Label ("Spiral"));
|
||||||
|
|
||||||
|
r = 0;
|
||||||
|
theta = 0.0;
|
||||||
|
|
||||||
|
foreach (string id in Gtk.Stock.ListIds ()) {
|
||||||
|
StockItem item = Gtk.Stock.Lookup (id);
|
||||||
|
if (item.Label == null)
|
||||||
|
continue;
|
||||||
|
|
||||||
|
pf.Put (new Gtk.Button (id), theta, r);
|
||||||
|
|
||||||
|
// Logarithmic spiral: r = a*e^(b*theta)
|
||||||
|
r += 5;
|
||||||
|
theta = 10 * Math.Log (10 * r);
|
||||||
|
}
|
||||||
|
|
||||||
|
win.ShowAll ();
|
||||||
|
|
||||||
|
Application.Run ();
|
||||||
|
}
|
||||||
|
|
||||||
|
static void Window_Delete (object obj, DeleteEventArgs args)
|
||||||
|
{
|
||||||
|
Application.Quit ();
|
||||||
|
args.RetVal = true;
|
||||||
|
}
|
||||||
|
}
|
Loading…
Reference in a new issue