[gxml] Continue on Implementing GDocument as DomDocument



commit 3f96e391850aaab4d4652c172bff1744e3f927f8
Author: Daniel Espinosa <esodan gmail com>
Date:   Tue Jul 12 20:24:07 2016 -0500

    Continue on Implementing GDocument as DomDocument
    
    * This make API changes on GXml.Document, by renaming
      create_element() and create_comment() to create_element_node() and
      create_comment_node(), this is to privilage DOM4 API
    
    * Added missing interfaces and implementations to implement most of
      DOM4 DomDocument
    
    This is a commit to save changes, it doen't compile, requires to fully
    implement all interfaces in Element and other objects to DOM4 interfaces

 gxml/Document.vala       |    4 +-
 gxml/DomCollections.vala |   52 ++++++++++++++
 gxml/DomDocument.vala    |    6 +-
 gxml/DomEvents.vala      |   13 ++--
 gxml/DomRange.vala       |   34 +++++----
 gxml/Element.vala        |   10 +++-
 gxml/GXmlDocument.vala   |  170 +++++++++++++++++++++++++++++++++++++-------
 gxml/GXmlDomEvents.vala  |   76 ++++++++++++++++++++
 gxml/GXmlDomRange.vala   |  175 ++++++++++++++++++++++++++++++++++++++++++++++
 gxml/GXmlNode.vala       |    2 +-
 gxml/Makefile.am         |    2 +
 gxml/Node.vala           |   35 +++++++++
 12 files changed, 524 insertions(+), 55 deletions(-)
---
diff --git a/gxml/Document.vala b/gxml/Document.vala
index 7fd87ea..3510a33 100644
--- a/gxml/Document.vala
+++ b/gxml/Document.vala
@@ -76,7 +76,7 @@ public interface GXml.Document : Object, GXml.Node
    * Is a matter of you to add as a child to any other
    * {@link GXml.Node}.
    */
-  public abstract GXml.Node create_element (string name) throws GLib.Error;
+  public abstract GXml.Node create_element_node (string name) throws GLib.Error;
   /**
    * Creates a new {@link GXml.Text}.
    *
@@ -90,7 +90,7 @@ public interface GXml.Document : Object, GXml.Node
    * Is a matter of you to add as a child to any other
    * {@link GXml.Node}, like a {@link GXml.Element} node.
    */
-  public abstract GXml.Node create_comment (string text);
+  public abstract GXml.Node create_comment_node (string text);
   /**
    * Creates a new {@link GXml.CDATA}.
    *
diff --git a/gxml/DomCollections.vala b/gxml/DomCollections.vala
index b9d7bdb..8241dc6 100644
--- a/gxml/DomCollections.vala
+++ b/gxml/DomCollections.vala
@@ -71,3 +71,55 @@ public interface GXml.DomNamedNodeMap : GLib.Object {
 }
 
 
+public interface GXml.DomNodeIterator {
+  public DomNode root { get; }
+  public DomNode reference_node { get; }
+  public bool pointer_before_reference_node { get; };
+  public ulong what_to_show { get; }
+  public DomNodeFilter? filter { get; }
+
+  public DomNode? next_node();
+  public DomNode? previous_node();
+
+  public void detach();
+}
+
+public class GXml.DomNodeFilter : Object {
+  // Constants for acceptNode()
+  public const ushort FILTER_ACCEPT = 1;
+  public const ushort FILTER_REJECT = 2;
+  public const ushort FILTER_SKIP = 3;
+
+  // Constants for whatToShow
+  public const ulong SHOW_ALL = 0xFFFFFFFF;
+  public const ulong SHOW_ELEMENT = 0x1;
+  public const ulong SHOW_ATTRIBUTE = 0x2; // historical
+  public const ulong SHOW_TEXT = 0x4;
+  public const ulong SHOW_CDATA_SECTION = 0x8; // historical
+  public const ulong SHOW_ENTITY_REFERENCE = 0x10; // historical
+  public const ulong SHOW_ENTITY = 0x20; // historical
+  public const ulong SHOW_PROCESSING_INSTRUCTION = 0x40;
+  public const ulong SHOW_COMMENT = 0x80;
+  public const ulong SHOW_DOCUMENT = 0x100;
+  public const ulong SHOW_DOCUMENT_TYPE = 0x200;
+  public const ulong SHOW_DOCUMENT_FRAGMENT = 0x400;
+  public const ulong SHOW_NOTATION = 0x800; // historical
+
+  public ushort acceptNode(Node node); // FIXME:
+}
+
+public interface GXml.DomTreeWalker : Object {
+  public abstract DomNode root { get; }
+  public abstract ulong what_to_show { get; }
+  public abstract DomNodeFilter? filter { get; }
+  public abstract DomNode current_node { get; }
+
+  public abstract DomNode? parentNode();
+  public abstract DomNode? firstChild();
+  public abstract DomNode? lastChild();
+  public abstract DomNode? previousSibling();
+  public abstract DomNode? nextSibling();
+  public abstract DomNode? previousNode();
+  public abstract DomNode? nextNode();
+}
+
diff --git a/gxml/DomDocument.vala b/gxml/DomDocument.vala
index 8f5cfde..422ae4d 100644
--- a/gxml/DomDocument.vala
+++ b/gxml/DomDocument.vala
@@ -36,15 +36,15 @@ public interface GXml.DomDocument : GLib.Object, GXml.DomNode, GXml.DomParentNod
   public abstract DomHTMLCollection get_elements_by_tag_name_ns (string? namespace, string local_name);
   public abstract DomHTMLCollection get_elements_by_class_name(string classNames);
 
-  public abstract DomElement create_element    (string localName);
+  public abstract DomElement create_element    (string local_name) throws GLib.Error;
   public abstract DomElement create_element_ns (string? namespace, string qualified_name);
   public abstract DomDocumentFragment create_document_fragment();
   public abstract DomText create_text_node (string data);
   public abstract DomComment create_comment (string data);
   public abstract DomProcessingInstruction create_processing_instruction (string target, string data);
 
-  public abstract DomNode import_node (DomNode node, bool deep = false);
-  public abstract DomNode adopt_node (DomNode node);
+  public abstract DomNode import_node (DomNode node, bool deep = false) throws GLib.Error;
+  public abstract DomNode adopt_node (DomNode node) throws GLib.Error;
 
   public abstract DomEvent create_event (string interface);
 
diff --git a/gxml/DomEvents.vala b/gxml/DomEvents.vala
index 72ec929..92e78a5 100644
--- a/gxml/DomEvents.vala
+++ b/gxml/DomEvents.vala
@@ -43,11 +43,7 @@ public interface GXml.DomEvent : GLib.Object {
 
   public abstract bool default_prevented { get; }
 
-  public const ushort NONE = 0;
-  public const ushort CAPTURING_PHASE = 1;
-  public const ushort AT_TARGET = 2;
-  public const ushort BUBBLING_PHASE = 3;
-  public abstract ushort event_phase { get; }
+  public abstract EventPhase event_phase { get; }
 
 
   public abstract void stop_propagation ();
@@ -56,6 +52,13 @@ public interface GXml.DomEvent : GLib.Object {
   public abstract void prevent_default ();
   public abstract void init_event (string type, bool bubbles, bool cancelable);
 
+       public enum EventPhase {
+               NONE = 0,
+               CAPTURING_PHASE,
+               AT_TARGET,
+               BUBBLING_PHASE
+       }
+
   [Flags]
   public enum Flags {
                STOP_PROPAGATION_FLAG,
diff --git a/gxml/DomRange.vala b/gxml/DomRange.vala
index fe96dde..c2c45b9 100644
--- a/gxml/DomRange.vala
+++ b/gxml/DomRange.vala
@@ -1,4 +1,4 @@
-/* -*- Mode: vala; indent-tabs-mode: t; c-basic-offset: 2; tab-width: 2 -*- */
+/* -*- Mode: vala; indent-tabs-mode: nil; c-basic-offset: 2; tab-width: 2 -*- */
 /*
  *
  * Copyright (C) 2016  Daniel Espinosa <esodan gmail com>
@@ -28,21 +28,17 @@ public interface GXml.DomRange {
   public abstract bool collapsed { get; }
   public abstract DomNode common_ancestor_container { get; }
 
-  public abstract void set_start        (DomNode node, ulong offset);
-  public abstract void set_end          (DomNode node, ulong offset);
-  public abstract void set_start_before (DomNode node);
-  public abstract void set_start_after  (DomNode node);
-  public abstract void set_end_before   (DomNode node);
-  public abstract void set_end_after    (DomNode node);
-  public abstract void collapse         (bool toStart = false);
-  public abstract void select_node      (DomNode node);
-  public abstract void select_node_contents (DomNode node);
-
-  public const ushort START_TO_START = 0;
-  public const ushort START_TO_END = 1;
-  public const ushort END_TO_END = 2;
-  public const ushort END_TO_START = 3;
-  public abstract ushort compare_boundary_points (ushort how, DomRange sourceRange);
+  public abstract void set_start        (DomNode node, ulong offset) throws GLib.Error;
+  public abstract void set_end          (DomNode node, ulong offset) throws GLib.Error;
+  public abstract void set_start_before (DomNode node) throws GLib.Error;
+  public abstract void set_start_after  (DomNode node) throws GLib.Error;
+  public abstract void set_end_before   (DomNode node) throws GLib.Error;
+  public abstract void set_end_after    (DomNode node) throws GLib.Error;
+  public abstract void collapse         (bool to_start = false) throws GLib.Error;
+  public abstract void select_node      (DomNode node) throws GLib.Error;
+  public abstract void select_node_contents (DomNode node) throws GLib.Error;
+
+  public abstract int compare_boundary_points (ushort how, DomRange sourceRange);
 
   public abstract void delete_contents ();
   public abstract DomDocumentFragment extract_contents();
@@ -59,4 +55,10 @@ public interface GXml.DomRange {
   public abstract bool  intersects_node   (DomNode node);
 
   public abstract string to_string ();
+  public enum BoundaryPoints {
+     START_TO_START = 0,
+     START_TO_END,
+     END_TO_END,
+     END_TO_START
+  }
 }
diff --git a/gxml/Element.vala b/gxml/Element.vala
index 3ddf41f..e365c6e 100644
--- a/gxml/Element.vala
+++ b/gxml/Element.vala
@@ -76,8 +76,16 @@ public interface GXml.Element : Object, GXml.Node
  * Convenient class for a list of {@link GXml.Element} objects based on
  * {@link Gee.ListArray}, with good support for bindings.
  */
-public class GXml.ElementList : ArrayList<GXml.Element>
+public class GXml.ElementList : ArrayList<GXml.Element>, GXml.DomHTMLCollection
 {
   public new GXml.Element get (int index) { return base.get (index); }
   public new GXml.Element[] to_array () { return (GXml.Element[]) ((Gee.Collection<GXml.Element>) 
this).to_array (); }
+  public ulong length { get { return (ulong) size; } }
+  public DomElement? item (ulong index) { get ((int) index); }
+  public DomElement? named_item (string name) {
+      foreach (GXml.Element e in this) {
+          if (e.name == name) return e;
+      }
+  }
+}
 }
diff --git a/gxml/GXmlDocument.vala b/gxml/GXmlDocument.vala
index 0a5244e..4d8d521 100644
--- a/gxml/GXmlDocument.vala
+++ b/gxml/GXmlDocument.vala
@@ -1,4 +1,4 @@
-/* GHtmlDocument.vala
+/* GDocument.vala
  *
  * Copyright (C) 2016  Daniel Espinosa <esodan gmail com>
  *
@@ -115,7 +115,7 @@ public class GXml.GDocument : GXml.GNode, GXml.Document
       return new GElement (this, r);
     }
   }
-  public GXml.Node create_comment (string text)
+  public GXml.Node create_comment_node (string text)
   {
     var c = doc->new_comment (text);
     return new GComment (this, c);
@@ -125,7 +125,7 @@ public class GXml.GDocument : GXml.GNode, GXml.Document
     var pi = doc->new_pi (target, data);
     return new GProcessingInstruction (this, pi);
   }
-  public GXml.Node create_element (string name) throws GLib.Error
+  public GXml.Node create_element_node (string name) throws GLib.Error
   {
     Xmlx.reset_last_error ();
     var el = doc->new_raw_node (null, name, null);
@@ -182,38 +182,103 @@ public class GXml.GDocument : GXml.GNode, GXml.Document
   }
   // DomDocument implementation
   protected Implementation _implementation = new Implementation ();
-  public abstract DomImplementation implementation { get { return _implementation; } }
-  public abstract string url { get; }
-  public abstract string document_uri { get; }
-  public abstract string origin { get; }
-  public abstract string compat_mode { get; }
-  public abstract string character_set { get; }
-  public abstract string content_type { get; }
+  protected string _url = "";
+  protected string _document_uri = "";
+  protected string _origin = "";
+  protected string _compat_mode = "";
+  protected string _character_set = "";
+  protected string _content_type = "";
+  public DomImplementation implementation { get { return _implementation; } }
+  public string url { get { return _url; } }
+  public string document_uri { get { return _document_uri; } }
+  public string origin { get { return _origin; } }
+  public string compat_mode { get { return _compat_mode; } }
+  public string character_set { get { return _character_set; } }
+  public string content_type { get { return _content_type; } }
 
-  public abstract DomDocumentType? doctype { get; }
-  public abstract DomElement? document_element { get; }
+  protected DomDocumentType _doctype = null;
+  public DomDocumentType? doctype { get { return _doctype; } }
+  public DomElement? document_element { get { return root; } }
 
-  public abstract DomHTMLCollection get_elements_by_tag_name (string local_name);
-  public abstract DomHTMLCollection get_elements_by_tag_name_ns (string? namespace, string local_name);
-  public abstract DomHTMLCollection get_elements_by_class_name(string classNames);
+  public DomElement create_element (string local_name) throws GLib.Error {
+      return create_element_node (local_name);
+  }
+  public DomElement create_element_ns (string? ns, string qualified_name) throws GLib.Error
+  {
+      var e = create_element (qualified_name);
+      e.set_namespace (ns, null);
+      return e;
+  }
+
+  public DomHTMLCollection get_elements_by_tag_name (string local_name) {
+      return get_elements_by_name (local_name);
+  }
+  public DomHTMLCollection get_elements_by_tag_name_ns (string? ns, string local_name) {
+      return get_elements_by_name_ns (local_name, ns);
+  }
+  public DomHTMLCollection get_elements_by_class_name(string class_names) {
+      return get_elements_by_property_value ("class", class_names);
+  }
 
-  //public abstract DomElement create_element    (string localName);
-  public abstract DomElement create_element_ns (string? namespace, string qualified_name);
-  public abstract DomDocumentFragment create_document_fragment();
-  public abstract DomText create_text_node (string data);
-  //public abstract DomComment create_comment (string data);
-  public abstract DomProcessingInstruction create_processing_instruction (string target, string data);
+  public DomDocumentFragment create_document_fragment() {
+    return new GDocumentFragment (this);
+  }
+  public DomText create_text_node (string data) {
+      return create_text (data);
+  }
+  public DomComment create_comment (string data) {
+      return create_comment_node (data);
+  }
+  public DomProcessingInstruction create_processing_instruction (string target, string data) {
+      return create_pi (target, data);
+  }
 
-  public abstract DomNode import_node (DomNode node, bool deep = false);
-  public abstract DomNode adopt_node (DomNode node);
+  public DomNode import_node (DomNode node, bool deep = false) throws GLib.Error {
+      if (node is DomDocument)
+        throw new GXml.DomError (GXml.DomError.NOT_SUPPORTED_ERROR,_("Can't import a Document"));
+      var dst = this.create_element_node ();
+      GXml.Node.copy (this, dst, node, deep);
+      return dst;
+  }
+  public DomNode adopt_node (DomNode node) throws GLib.Error {
+      if (node is DomDocument)
+        throw new GXml.DomError (GXml.DomError.NOT_SUPPORTED_ERROR,_("Can't adopt a Document"));
+      var dst = this.create_element_node (node.node_name);
+      GXml.Node.copy (this, dst, node, deep);
+      if (node.parent != null)
+        node.parent.children.remove_at (node.parent.children.index_of (node));
+      return dst;
+  }
 
-  public abstract DomEvent create_event (string interface);
+  protected GLib.Object _constructor;
+  public abstract DomEvent create_event (string iface) {
+      var s = iface.down ();
+      if (s == "customevent") _constructor = new GXml.GDomCustomEvent ();
+      if (s == "event") _constructor = new GXml.GDomCustomEvent ();
+      if (s == "events") _constructor = new GXml.GDomCustomEvent ();
+      if (s == "htmlevents") _constructor = new GXml.GDomCustomEvent ();
+      if (s == "keyboardevent") _constructor = null;
+      if (s == "keyevents") _constructor = null;
+      if (s == "messageevent") _constructor = null;
+      if (s == "mouseevent") _constructor = null;
+      if (s == "mouseevents") _constructor = null;
+      if (s == "touchevent") _constructor = null;
+      if (s == "uievent") _constructor = null;
+      if (s == "uievents") _constructor = null;
+  }
 
-  public abstract DomRange create_range();
+  public DomRange create_range() {
+      return new GDomRange ();
+  }
 
   // NodeFilter.SHOW_ALL = 0xFFFFFFFF
-  public abstract DomNodeIterator create_node_iterator (DomNode root, ulong whatToShow = (ulong) 0xFFFFFFFF, 
DomNodeFilter? filter = null);
-  public abstract DomTreeWalker create_tree_walker (DomNode root, ulong what_to_show = (ulong) 0xFFFFFFFF, 
DomNodeFilter? filter = null);
+  public DomNodeIterator create_node_iterator (DomNode root, ulong what_to_show = (ulong) 0xFFFFFFFF, 
DomNodeFilter? filter = null)
+  {
+    return new GDomNodeIterator (root, what_to_show, filter);
+  }
+  public DomTreeWalker create_tree_walker (DomNode root, ulong what_to_show = (ulong) 0xFFFFFFFF, 
DomNodeFilter? filter = null) {
+      return new GDomTreeWolker (root, what_to_show, filter);
+  }
 }
 
 
@@ -255,3 +320,54 @@ public class GXml.GDocumentType : GXml.GNode, GXml.DomNode, GXml.DomChildNode, G
     get_internal_node ()->unlink ();
   }
 }
+
+public class GXml.GDocumentFragment : GXml.GNode, GXml.DomDocumentFragment {
+    public GDocumentFragment (GXml.GDocument doc)  {
+        document = doc;
+    }
+}
+
+
+public class GXml.GDomNodeIterator : Object, GXml.DomNodeIterator {
+  protected DomNode _root;
+  protected DomNode _reference_node;
+  protected DomNode _pointer_before_reference_node;
+  protected DomNode _what_to_show;
+  protected DomFilter _filter;
+  public GDomNodeIterator (DomNode n, what_to_show, filter) {
+    _root = n;
+    _what_to_show = what_to_show;
+    _filter = filter;
+  }
+  public DomNode root { get { return _root; } }
+  public DomNode reference_node { get { return _reference_node; }} }
+  public bool pointer_before_reference_node { get { return _pointer_before_reference_node; } };
+  public ulong what_to_show { get { return _what_to_show; } }
+  public DomNodeFilter? filter { get { return _filter; } }
+
+  public DomNode? next_node() { return null; // FIXME;}
+  public DomNode? previous_node() { return null; // FIXME;}
+
+  public void detach() { return null; // FIXME;}
+}
+
+
+public class GXml.GDomTreeWalker : Object, GXml.DomTreeWalker {
+  protected DomNode root { get; }
+  protected ulong _what_to_show;
+  protected DomNodeFilter? _filter;
+  protected  DomNode _current_node;
+
+  public DomNode root { get; }
+  public ulong what_to_show { get; }
+  public DomNodeFilter? filter { get; }
+  public DomNode current_node { get; }
+
+  public DomNode? parentNode() { return null; // FIXME: }
+  public DomNode? firstChild() { return null; // FIXME: }
+  public DomNode? lastChild() { return null; // FIXME: }
+  public DomNode? previousSibling() { return null; // FIXME: }
+  public DomNode? nextSibling() { return null; // FIXME: }
+  public DomNode? previousNode() { return null; // FIXME: }
+  public DomNode? nextNode() { return null; // FIXME: }
+}
diff --git a/gxml/GXmlDomEvents.vala b/gxml/GXmlDomEvents.vala
new file mode 100644
index 0000000..a206e9e
--- /dev/null
+++ b/gxml/GXmlDomEvents.vala
@@ -0,0 +1,76 @@
+/* -*- Mode: vala; indent-tabs-mode: t; c-basic-offset: 2; tab-width: 2 -*- */
+/*
+ *
+ * Copyright (C) 2016  Daniel Espinosa <esodan gmail com>
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, see <http://www.gnu.org/licenses/>.
+ *
+ * Authors:
+ *      Daniel Espinosa <esodan gmail com>
+ */
+
+public class GXml.GDomEvent : Object, GXml.DomEvent {
+       protected string _etype;
+       protected DomEventTarget _target;
+       protected DomEventTarget _current_target;
+       protected bool _bubbles;
+       protected bool _cancelable;
+       public string etype { get { return _etype; } }
+       public DomEventTarget? target { get { return _target; } }
+       public DomEventTarget? current_target { get { return _current_target; } }
+       public bool bubbles { get { return _bubbles; } }
+       public bool cancelable { get { return _cancelable; } }
+
+       protected bool _is_trusted = false;
+       public bool is_trusted { get { return _is_trusted; } }
+       protected DomTimeStamp _time_stamp = new DomTimeStamp ();
+       public DomTimeStamp time_stamp { get { return _time_stamp; } }
+
+       protected bool _default_prevented;
+       public bool default_prevented { get { return _default_prevented; } }
+
+       protected  EventPhase _event_phase;
+       public EventPhase event_phase { get { return _event_phase; } }
+
+       protected GXml.DomEvent.Flags _flags;
+       public abstract void stop_propagation () {
+               _flags = _flags && GXml.DomEvent.Flags.STOP_PROPAGATION_FLAG;
+       }
+       public abstract void stop_immediate_propagation () {
+               _flags = _flags && GXml.DomEvent.Flags.STOP_IMMEDIATE_PROPAGATION_FLAG;
+       }
+
+       public abstract void prevent_default () {
+               if (cancelable)
+                       _flags = _flags && GXml.DomEvent.Flags.CANCELED_FLAG;
+       }
+       public void init_event (string type, bool bubbles, bool cancelable) {
+               _etype = type;
+               _bubbles = bubbles;
+               _cancelable = cancelable;
+       }
+}
+
+public class GXml.GDomCustomEvent : GXml.GDomEvent {
+       protected GLib.Value? _detail;
+       public GLib.Value? detail { get { return _detail; } }
+
+       public void init_custom_event (string type, bool bubbles, bool cancelable, GLib.Value? detail)
+       {
+               _etype = type;
+               _bubbles = bubbles;
+               _cancelable = cancelable;
+               _detail = detail;
+       }
+}
diff --git a/gxml/GXmlDomRange.vala b/gxml/GXmlDomRange.vala
new file mode 100644
index 0000000..e3fc2df
--- /dev/null
+++ b/gxml/GXmlDomRange.vala
@@ -0,0 +1,175 @@
+/* -*- Mode: vala; indent-tabs-mode: t; c-basic-offset: 2; tab-width: 2 -*- */
+/*
+ *
+ * Copyright (C) 2016  Daniel Espinosa <esodan gmail com>
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, see <http://www.gnu.org/licenses/>.
+ *
+ * Authors:
+ *      Daniel Espinosa <esodan gmail com>
+ */
+
+public class GXml.GDomRange : Object, GXml.DomRange {
+       protected DomNode _start_container;
+       protected ulong _start_offset;
+       protected DomNode _end_container;
+       protected ulong _end_offset;
+       protected bool _collapse;
+       protected DomNode _common_ancestor_container;
+       public DomNode start_container { get { return _start_container; } }
+       public ulong start_offset { get { return _start_offset; } }
+       public DomNode end_container { get { return _end_container; } }
+       public ulong end_offset { get { return _end_offset; } }
+       public bool collapsed { get { return _collapse; } }
+       public DomNode common_ancestor_container { get { return _common_ancestor_container; } }
+
+       public void set_start (DomNode node, ulong offset) throws GLib.Error {
+               if (node is DomDocumentType)
+                       throw new DomError.INVALID_NODE_TYPE_ERROR (_("Invalid node type to start"));
+               if (offset > node.length)
+                       throw new DomError.INDEX_SIZE_ERROR (_("Invalid offset for node to start"));
+               if (_end_container != null) {
+                       if (node.parent != _end_container.parent) {
+                               _start_container = _end_container;
+                               _start_offset = _end_offset;
+                       } else {
+                               var ni = node.parent.children.index_of (node);
+                               var ei = node.parent.children.index_of (_end_offset);
+                               if (ni > ei)
+                                       _end_container = node;
+                               _start_container = node;
+                               _start_offset = offset;
+                       }
+               }
+               _start_container = node;
+               _start_offset = offset;
+       }
+       public void set_end          (DomNode node, ulong offset) throws GLib.Error {
+               if (node is DomDocumentType)
+                       throw new DomError.INVALID_NODE_TYPE_ERROR (_("Invalid node type to start"));
+               if (offset > node.length)
+                       throw new DomError.INDEX_SIZE_ERROR (_("Invalid offset for node to start"));
+               if (_start_container != null) {
+                       if (node.parent != _start_container.parent) {
+                               _end_container = _start_container;
+                               _end_offset = _start_offset;
+                       } else {
+                               var ni = node.parent.children.index_of (node);
+                               var ei = node.parent.children.index_of (_start_offset);
+                               if (ni > ei)
+                                       _start_container = node;
+                       }
+               }
+               _end_container = node;
+               _end_offset = offset;
+       }
+       public void set_start_before (DomNode node) throws GLib.Error {
+               if (node.parent == null)
+                       throw new DomError.INVALID_NODE_TYPE_ERROR (_("Invalid node type to start before"));
+               set_start (node.parent, node.parent.children.index_of (node));
+       }
+       public void set_start_after  (DomNode node) throws GLib.Error {
+               if (node.parent == null)
+                       throw new DomError.INVALID_NODE_TYPE_ERROR (_("Invalid node type to start after"));
+               var i = node.parent.children.index_of (node);
+               if (i+1 < node.parent.children.size)
+                       set_start (node.parent, node.parent.children.index_of (node) + 1);
+               else
+                       set_start (node.parent, node.parent.children.index_of (node));
+       }
+       public void set_end_before (DomNode node) throws GLib.Error {
+               if (node.parent == null)
+                       throw new DomError.INVALID_NODE_TYPE_ERROR (_("Invalid node type to start before"));
+               set_end (node.parent, node.parent.children.index_of (node));
+       }
+       public void set_end_after (DomNode node) throws GLib.Error {
+               if (node.parent == null)
+                       throw new DomError.INVALID_NODE_TYPE_ERROR (_("Invalid node type to start after"));
+               var i = node.parent.children.index_of (node);
+               if (i+1 < node.parent.children.size)
+                       set_end (node.parent, node.parent.children.index_of (node) + 1);
+               else
+                       set_end (node.parent, node.parent.children.index_of (node));
+       }
+       public abstract void collapse (bool to_start = false) throws GLib.Error {
+               if (to_start) {
+                       _end_container = _start_container;
+                       _end_offset = _start_offset;
+               } else {
+                       _start_container = _end_container;
+                       _start_offset = _end_offset;
+               }
+       }
+       public void select_node (DomNode node) throws GLib.Error {
+               if (node.parent == null)
+                       throw new DomError.INVALID_NODE_TYPE_ERROR (_("Invalid node type to start after"));
+               var i = node.parent.children.index_of (node);
+               set_start (node.parent, i);
+               if (i + 1 < node.parent.children.size)
+                       set_end (node.parent, i + 1);
+               else
+                       set_end (node.parent, i);
+       }
+       public void select_node_contents (DomNode node) throws GLib.Error {
+               if (node is DomDocumentType)
+                       throw new DomError.INVALID_NODE_TYPE_ERROR (_("Invalid node type to start"));
+               set_start (node, 0);
+               set_end (node, node.length);
+       }
+
+       public abstract int compare_boundary_points (BoundaryPoints how, DomRange source_range) throws 
GLib.Error {
+               if (_start_container.parent != source_range.start_container.parent)
+                       throw new DomError.WRONG_DOCUMENT_ERROR (_("Invalid root's in range"));
+               switch (how) {
+                       case BoundaryPoints.START_TO_START:
+                               set_start (_start_container, 0);
+                               set_end (source_range.start_container, 0);
+                               return 0;
+                               break;
+                       case BoundaryPoints.START_TO_END:
+                               set_start (_start_container, _start_container.children.size);
+                               set_end (source_range.end_container, 0);
+                               return -1;
+                               break;
+                       case BoundaryPoints.END_TO_END:
+                               set_start (_end_container, 0);
+                               set_end (source_range.end_container, 0);
+                               return 0;
+                               break;
+                       case BoundaryPoints.END_TO_START:
+                               set_start (_start_container, 0);
+                               set_end (source_range.end_container, 0);
+                               return 1;
+                               break;
+               }
+               return 0;
+       }
+
+       public void delete_contents () { return; // FIXME: }
+       public DomDocumentFragment extract_contents() { return null; // FIXME:
+       }
+       public DomDocumentFragment clone_contents() { return null; // FIXME: }
+       public void insertNode(DomNode node) { return null; // FIXME: }
+       public void surroundContents(DomNode newParent) { return null; // FIXME: }
+
+       public DomRange clone_range() { return this; // FIXME: }
+       public void detach () { return; // FIXME: }
+
+       public bool  is_point_in_range (DomNode node, ulong offset) { return false; // FIXME: }
+       public short compare_point     (DomNode node, ulong offset) { return 0; // FIXME: }
+
+       public bool  intersects_node   (DomNode node) { return false; // FIXME: }
+
+       public string to_string ()  { return "DomRange"; // FIXME: }
+}
diff --git a/gxml/GXmlNode.vala b/gxml/GXmlNode.vala
index 33dcb40..4f78d7d 100644
--- a/gxml/GXmlNode.vala
+++ b/gxml/GXmlNode.vala
@@ -25,7 +25,7 @@ using Gee;
 /**
  * Base interface providing basic functionalities to all GXml interfaces.
  */
-public abstract class GXml.GNode : Object, GXml.Node
+public abstract class GXml.GNode : Object, GXml.Node, GXml.DomNode
 {
   protected GXml.GDocument _doc;
   protected Xml.Node *_node;
diff --git a/gxml/Makefile.am b/gxml/Makefile.am
index a462772..85928b5 100644
--- a/gxml/Makefile.am
+++ b/gxml/Makefile.am
@@ -86,6 +86,7 @@ sources = \
        GXmlComment.vala \
        GXmlCDATA.vala \
        GXmlDocument.vala \
+       GXmlDomEvents.vala \
        GXmlElement.vala \
        GXmlNamespace.vala \
        GXmlNode.vala \
@@ -94,6 +95,7 @@ sources = \
        GXmlHashMapAttr.vala \
        GXmlListChildren.vala \
        GXmlListNamespaces.vala \
+       GXmlDomRange.val \
        DomAttr.vala \
        DomCharacter.vala \
        DomCollections.vala \
diff --git a/gxml/Node.vala b/gxml/Node.vala
index 35ade37..826016a 100644
--- a/gxml/Node.vala
+++ b/gxml/Node.vala
@@ -103,6 +103,41 @@ public interface GXml.Node : Object
     return list;
   }
   /**
+   * Search all child {@link GXml.Element} with a given name.
+   */
+  public virtual GXml.ElementList
+   get_elements_by_name (string name)
+  {
+    var list = new GXml.ElementList ();
+    if (!(this is GXml.Element || this is GXml.Document)) return list;
+    foreach (var child in children) {
+      if (child is GXml.Element) {
+        list.add_all (child.get_elements_by_name (name));
+        if (name == child.name)
+          list.add ((GXml.Element) child);
+      }
+    }
+    return list;
+  }
+  /**
+   * Search all child {@link GXml.Element} with a given name and namespace URI.
+   */
+  public virtual GXml.ElementList
+   get_elements_by_name_ns (string name, string? ns)
+  {
+    var list = new GXml.ElementList ();
+    if (!(this is GXml.Element || this is GXml.Document)) return list;
+    foreach (var child in children) {
+      if (child is GXml.Element) {
+        list.add_all (child.get_elements_by_name (name));
+        if (!(child.namespace == null && ns == null)) continue;
+        if (name == child.name && child.namespace.uri == ns)
+          list.add ((GXml.Element) child);
+      }
+    }
+    return list;
+  }
+  /**
    * Node's string representation.
    */
   public abstract string to_string ();


[Date Prev][Date Next]   [Thread Prev][Thread Next]   [Thread Index] [Date Index] [Author Index]