gflow-simple-sink.vala 6.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188
  1. /********************************************************************
  2. # Copyright 2014-2022 Daniel 'grindhold' Brendle, 2015 Daniel Espinosa <esodan@gmail.com>
  3. #
  4. # This file is part of libgtkflow.
  5. #
  6. # libgtkflow is free software: you can redistribute it and/or
  7. # modify it under the terms of the GNU Lesser General Public License
  8. # as published by the Free Software Foundation, either
  9. # version 3 of the License, or (at your option) any later
  10. # version.
  11. #
  12. # libgtkflow is distributed in the hope that it will be
  13. # useful, but WITHOUT ANY WARRANTY; without even the implied
  14. # warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
  15. # PURPOSE. See the GNU Lesser General Public License for more details.
  16. #
  17. # You should have received a copy of the GNU Lesser General Public
  18. # License along with libgtkflow.
  19. # If not, see http://www.gnu.org/licenses/.
  20. *********************************************************************/
  21. namespace GFlow {
  22. /**
  23. * A simple implementation of {@link GFlow.Sink}.
  24. */
  25. public class SimpleSink : Object, Dock, Sink {
  26. // Dock interface
  27. protected GLib.Type _type = GLib.Type.NONE;
  28. private string? _name = null;
  29. /**
  30. * This SimpleSink's displayname
  31. */
  32. public string? name {
  33. get { return this._name; }
  34. set { this._name = value; }
  35. }
  36. public string? _typename = null;
  37. /**
  38. * This SimpleSink's typestring
  39. */
  40. public string? typename {
  41. get { return this._typename; }
  42. set { this._typename = value; }
  43. }
  44. /**
  45. * Defines how many sources can be connected to this sink
  46. *
  47. * Setting this variable to a lower value than the current
  48. * amount of connected sources will have no further effects
  49. * than not allowing more connections.
  50. */
  51. public uint max_sources {get; set; default=1;}
  52. /**
  53. * Indicates whether this Sink should be rendered highlighted
  54. */
  55. public bool highlight { get; set; default = false; }
  56. /**
  57. * Indicates whether this Sink should be rendered active
  58. */
  59. public bool active {get; set; default=false;}
  60. /**
  61. * A reference to the {@link Node} that this SimpleSink resides in
  62. */
  63. public weak Node? node { get; set; }
  64. /**
  65. * The type that this SimpleSink was initialized with
  66. */
  67. public GLib.Type value_type { get { return _type; } }
  68. // Sink Interface
  69. private List<Source> _sources = new List<Source> ();
  70. /**
  71. * The {@link Source}s that this SimpleSink is currently connected to
  72. */
  73. public List<Source> sources { get { return _sources; } }
  74. /**
  75. * Connects this SimpleSink to the given {@link Source}. This will
  76. * only succeed if both {@link Dock}s are of the same type. If this
  77. * is not the case, an exception will be thrown
  78. */
  79. protected void add_source(Source s) throws Error
  80. {
  81. if (this.value_type != s.value_type) {
  82. throw new NodeError.INCOMPATIBLE_SINKTYPE(
  83. "Can't connect. Source has type %s while Sink has type %s".printf(
  84. s.value_type.name(), this.value_type.name()
  85. )
  86. );
  87. }
  88. this._sources.append(s);
  89. s.changed.connect(this.do_source_changed);
  90. }
  91. /**
  92. * Destroys the connection between this SimpleSink and the given {@link Source}
  93. */
  94. protected void remove_source (Source s) throws GLib.Error
  95. {
  96. if (this._sources.index(s) != -1)
  97. this._sources.remove(s);
  98. if (s.is_linked_to(this)) {
  99. s.unlink (this);
  100. this.unlinked(s, this._sources.length () == 0);
  101. }
  102. }
  103. /**
  104. * Creates a new SimpleSink with type of given value {@link GLib.Value}
  105. */
  106. public SimpleSink(GLib.Value value) {
  107. _type = value.type();
  108. }
  109. /**
  110. * Creates a new SimpleSink with given type {@link GLib.Type}
  111. */
  112. public SimpleSink.with_type(GLib.Type type) {
  113. _type = type;
  114. }
  115. /**
  116. * Returns true if this sink is connected to at least one source
  117. */
  118. public bool is_linked() {
  119. return this.sources.length() > 0;
  120. }
  121. /**
  122. * Returns true if this SimpleSink is connected to the given {@link Dock}
  123. */
  124. public bool is_linked_to (Dock dock) { // FIXME Use more logic to know Source type, value or name
  125. if (!(dock is Source)) return false;
  126. return this._sources.index((Source) dock) != -1;
  127. }
  128. /**
  129. * Disconnect from the given {@link Dock}
  130. */
  131. public new void unlink (Dock dock) throws GLib.Error {
  132. if (!this.is_linked_to (dock)) return;
  133. if (dock is Source) {
  134. this.remove_source((Source) dock);
  135. this.do_source_changed();
  136. dock.unlinked(this, this.sources.length() == 0);
  137. dock.changed.disconnect(this.do_source_changed);
  138. }
  139. }
  140. private void do_source_changed(Value? source_value = null, string? flow_id = null) {
  141. changed(source_value, flow_id);
  142. }
  143. /**
  144. * Connect to the given {@link Dock}
  145. */
  146. public new void link (Dock dock) throws GLib.Error {
  147. if (this.is_linked_to (dock)) return;
  148. if (!this.before_linking(this, dock)) return;
  149. if (this._sources.length()+1 > this.max_sources && this.sources.length() > 0) {
  150. this.unlink(this.sources.nth_data(this.sources.length()-1));
  151. }
  152. if (dock is Source) {
  153. var source = dock as Source;
  154. add_source(source);
  155. do_source_changed(source.get_last_value ());
  156. dock.link (this);
  157. linked (dock);
  158. }
  159. }
  160. /**
  161. * Disconnect from any {@link Dock} that this SimpleSink is connected to
  162. */
  163. public new void unlink_all() throws GLib.Error {
  164. foreach (Source s in this._sources)
  165. if (s != null)
  166. this.unlink(s);
  167. }
  168. }
  169. }