dock_renderer.vala 9.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239
  1. /********************************************************************
  2. # Copyright 2014-2022 Daniel 'grindhold' Brendle
  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 GtkFlow {
  22. public abstract class DockRenderer : GLib.Object {
  23. /**
  24. * Default value for the dock's dockpoint size.
  25. * Used for both height and width
  26. */
  27. public int dockpoint_height {get;set;default=16;}
  28. /**
  29. * Spacing between caption and dockpoint
  30. */
  31. public int spacing_x {get; set; default=5;}
  32. /**
  33. * Vertical spacing between docks
  34. */
  35. public int spacing_y {get; set; default=3;}
  36. /**
  37. * This signal is to be emitted whenever the size of this dock changes
  38. */
  39. public signal void size_changed();
  40. /**
  41. * Draw this dockrenderer's {@link GFlow.Dock} on the given
  42. * {@link Cairo.Context}
  43. */
  44. public abstract void draw_dock(Gtk.Widget w, Cairo.Context cr, Gtk.StyleContext sc,
  45. int offset_x, int offset_y, int width);
  46. /**
  47. * Implementations should return this dock's minimal height
  48. */
  49. public abstract int get_min_height();
  50. /**
  51. * Implementations should return this dock's minimal width
  52. */
  53. public abstract int get_min_width();
  54. /**
  55. * Implementations should update the graphical representation of the
  56. * dock's captionstring and typestring. If typestrings should be displayed,
  57. * the parameter show_types will be true
  58. */
  59. public abstract void update_name_layout(bool show_types);
  60. /**
  61. * Return the dock that belongs to this dockrenderer
  62. */
  63. public abstract GFlow.Dock get_dock();
  64. }
  65. private class DefaultDockRenderer : DockRenderer {
  66. private Pango.Layout layout = null;
  67. private GFlow.Dock d = null;
  68. public DefaultDockRenderer(Node n, GFlow.Dock d) {
  69. this.d = d;
  70. this.layout = (new Gtk.Label("")).create_pango_layout("");
  71. }
  72. public override GFlow.Dock get_dock () {
  73. return this.d;
  74. }
  75. public override void update_name_layout(bool show_types) {
  76. string labelstring;
  77. string name = this.d.name ?? "";
  78. string typename = this.d.typename ?? this.d.determine_typestring();
  79. if (show_types) {
  80. labelstring = "<i>%s</i> : %s".printf( typename, name );
  81. } else {
  82. labelstring = name;
  83. }
  84. this.layout.set_markup(labelstring, -1);
  85. this.size_changed();
  86. }
  87. /**
  88. * Get the minimum width for this dock
  89. */
  90. public override int get_min_height() {
  91. int width, height;
  92. this.layout.get_pixel_size(out width, out height);
  93. return (int)(Math.fmax(height, dockpoint_height))+spacing_y;
  94. }
  95. /**
  96. * Get the minimum height for this dock
  97. */
  98. public override int get_min_width() {
  99. int width, height;
  100. this.layout.get_pixel_size(out width, out height);
  101. return (int)(width + dockpoint_height + spacing_y);
  102. }
  103. public override void draw_dock(Gtk.Widget w, Cairo.Context cr, Gtk.StyleContext sc,
  104. int offset_x, int offset_y, int width) {
  105. if ((w.get_style_context().get_state() & Gtk.StateFlags.DIR_LTR ) > 0) {
  106. if (d is GFlow.Sink)
  107. draw_sink(w, cr, sc, offset_x, offset_y, width);
  108. if (d is GFlow.Source)
  109. draw_source(w, cr, sc, offset_x, offset_y, width);
  110. } else {
  111. if (d is GFlow.Sink)
  112. draw_sink_rtl(w, cr, sc, offset_x, offset_y, width);
  113. if (d is GFlow.Source)
  114. draw_source_rtl(w, cr, sc, offset_x, offset_y, width);
  115. }
  116. }
  117. /**
  118. * Draw the given source onto a cairo context
  119. */
  120. public void draw_source(Gtk.Widget w, Cairo.Context cr, Gtk.StyleContext sc,
  121. int offset_x, int offset_y, int width) {
  122. Gtk.StateFlags flags = Gtk.StateFlags.NORMAL;
  123. if (this.d.is_linked())
  124. flags = Gtk.StateFlags.CHECKED;
  125. if (this.d.highlight)
  126. flags |= Gtk.StateFlags.PRELIGHT;
  127. if (this.d.active)
  128. flags |= Gtk.StateFlags.ACTIVE;
  129. int option_height=16;
  130. int option_width=16;
  131. int option_x=offset_x+width-dockpoint_height-4;
  132. int option_y=offset_y;
  133. draw_radio(w, cr, option_x, option_y,
  134. flags, &option_height, &option_width);
  135. sc.save();
  136. sc.add_class(Gtk.STYLE_CLASS_BUTTON);
  137. Gdk.RGBA col = sc.get_color(Gtk.StateFlags.NORMAL);
  138. cr.set_source_rgba(col.red,col.green,col.blue,col.alpha);
  139. cr.move_to(offset_x + width - this.get_min_width(), offset_y);
  140. Pango.cairo_show_layout(cr, this.layout);
  141. sc.restore();
  142. }
  143. /**
  144. * Draw the given source onto a cairo context for right-to-left-scriptures
  145. */
  146. public void draw_sink_rtl(Gtk.Widget w, Cairo.Context cr, Gtk.StyleContext sc,
  147. int offset_x, int offset_y, int width) {
  148. Gtk.StateFlags flags = Gtk.StateFlags.NORMAL;
  149. if (this.d.is_linked())
  150. flags = Gtk.StateFlags.CHECKED;
  151. if (this.d.highlight)
  152. flags |= Gtk.StateFlags.PRELIGHT;
  153. if (this.d.active)
  154. flags |= Gtk.StateFlags.ACTIVE;
  155. int option_height=16;
  156. int option_width=16;
  157. int option_x=offset_x+width-dockpoint_height-24;
  158. int option_y=offset_y;
  159. draw_radio(w, cr, option_x, option_y,
  160. flags, &option_height, &option_width);
  161. sc.save();
  162. sc.add_class(Gtk.STYLE_CLASS_BUTTON);
  163. Gdk.RGBA col = sc.get_color(Gtk.StateFlags.NORMAL);
  164. cr.set_source_rgba(col.red,col.green,col.blue,col.alpha);
  165. cr.move_to(offset_x + width - this.get_min_width() - 24, offset_y);
  166. Pango.cairo_show_layout(cr, this.layout);
  167. sc.restore();
  168. }
  169. /**
  170. * Draw the given sink onto a cairo context
  171. */
  172. public void draw_sink(Gtk.Widget w, Cairo.Context cr, Gtk.StyleContext sc,
  173. int offset_x, int offset_y, int width) {
  174. Gtk.StateFlags flags = Gtk.StateFlags.NORMAL;
  175. if (this.d.is_linked())
  176. flags = Gtk.StateFlags.CHECKED;
  177. if (this.d.highlight)
  178. flags |= Gtk.StateFlags.PRELIGHT;
  179. if (this.d.active)
  180. flags |= Gtk.StateFlags.ACTIVE;
  181. int option_height=16;
  182. int option_width=16;
  183. int option_x=offset_x-4;
  184. int option_y=offset_y;
  185. draw_radio(w, cr, option_x, option_y,
  186. flags, &option_height, &option_width);
  187. sc.save();
  188. sc.add_class(Gtk.STYLE_CLASS_BUTTON);
  189. Gdk.RGBA col = sc.get_color(Gtk.StateFlags.NORMAL);
  190. cr.set_source_rgba(col.red,col.green,col.blue,col.alpha);
  191. cr.move_to(offset_x+dockpoint_height+spacing_x, offset_y);
  192. Pango.cairo_show_layout(cr, this.layout);
  193. sc.restore();
  194. }
  195. /**
  196. * Draw the given sink onto a cairo context for right-to-left-scriptures
  197. */
  198. public void draw_source_rtl(Gtk.Widget w, Cairo.Context cr, Gtk.StyleContext sc,
  199. int offset_x, int offset_y, int width) {
  200. Gtk.StateFlags flags = Gtk.StateFlags.NORMAL;
  201. if (this.d.is_linked())
  202. flags = Gtk.StateFlags.CHECKED;
  203. if (this.d.highlight)
  204. flags |= Gtk.StateFlags.PRELIGHT;
  205. if (this.d.active)
  206. flags |= Gtk.StateFlags.ACTIVE;
  207. int option_height=16;
  208. int option_width=16;
  209. int option_x=offset_x + 16;
  210. int option_y=offset_y;
  211. draw_radio(w, cr, option_x, option_y,
  212. flags, &option_height, &option_width);
  213. sc.save();
  214. sc.add_class(Gtk.STYLE_CLASS_BUTTON);
  215. Gdk.RGBA col = sc.get_color(Gtk.StateFlags.NORMAL);
  216. cr.set_source_rgba(col.red,col.green,col.blue,col.alpha);
  217. cr.move_to(offset_x+dockpoint_height+spacing_x+20, offset_y);
  218. Pango.cairo_show_layout(cr, this.layout);
  219. sc.restore();
  220. }
  221. }
  222. }