tracklist.vala 9.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297
  1. /********************************************************************
  2. # Copyright 2014 Daniel 'grindhold' Brendle
  3. #
  4. # This file is part of Rainbow Lollipop.
  5. #
  6. # Rainbow Lollipop is free software: you can redistribute it and/or
  7. # modify it under the terms of the GNU 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. # Rainbow Lollipop 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 General Public License for more details.
  16. #
  17. # You should have received a copy of the GNU General Public
  18. # License along with Rainbow Lollipop.
  19. # If not, see http://www.gnu.org/licenses/.
  20. *********************************************************************/
  21. namespace RainbowLollipop {
  22. /**
  23. * TrackListBackground is a half-transparent overlay over the WebViews
  24. * that optically emphasizes, that TrackList is a modal.
  25. */
  26. public class TrackListBackground : Clutter.Actor {
  27. /**
  28. * Construct a new TrackListBackground
  29. */
  30. public TrackListBackground(Clutter.Actor stage) {
  31. var tl = new TrackList(this);
  32. this.visible = true;
  33. this.add_constraint(
  34. new Clutter.BindConstraint(stage, Clutter.BindCoordinate.SIZE,0)
  35. );
  36. this.background_color = Clutter.Color.from_string(Config.c.colorscheme.tracklist);
  37. this.transitions_completed.connect(do_transitions_completed);
  38. var action = new Clutter.PanAction();
  39. action.pan_axis = Clutter.PanAxis.Y_AXIS;
  40. action.interpolate = true;
  41. action.deceleration = 0.75;
  42. this.add_action(action);
  43. this.reactive = true;
  44. this.add_child(tl);
  45. }
  46. /**
  47. * Fade in
  48. */
  49. public void emerge() {
  50. var tl = (TrackList)this.get_first_child();
  51. if (tl != null)
  52. tl.emerge();
  53. this.visible = true;
  54. this.save_easing_state();
  55. this.opacity = 0xE0;
  56. this.restore_easing_state();
  57. }
  58. /**
  59. * Fade out
  60. */
  61. public void disappear() {
  62. var tl = (TrackList)this.get_first_child();
  63. if (tl != null)
  64. tl.disappear();
  65. this.save_easing_state();
  66. this.opacity = 0x00;
  67. this.restore_easing_state();
  68. }
  69. private void do_transitions_completed() {
  70. if (this.opacity == 0x00) {
  71. this.visible = false;
  72. }
  73. }
  74. }
  75. /**
  76. * Represents a list of the currently opened HistoryTracks.
  77. * The Tracklist also contains a special Track which is called
  78. * the EmptyTrack. The EmptyTrack offers users the possibility
  79. * to open new Websites
  80. */
  81. public class TrackList : Clutter.Actor {
  82. /**
  83. * Holds a reference to the currently active HistoryTrack
  84. * of this TrackList.
  85. * The current_track is always the HistoryTrack that's associated
  86. * WebView is currently displayed in the foreground
  87. */
  88. public HistoryTrack? current_track {
  89. get {
  90. return this._current_track;
  91. }
  92. set {
  93. if (this._current_track != null)
  94. this._current_track.cleanup();
  95. this._current_track = value;
  96. if (this._current_track != null)
  97. this._current_track.prepare();
  98. }
  99. }
  100. private HistoryTrack? _current_track;
  101. private EmptyTrack empty_track;
  102. private Clutter.BoxLayout boxlayout;
  103. /**
  104. * This is a stash for urls that have to be loaded after the
  105. * User decided to either begin a new session or load an old one
  106. * This is usually needed when rainbow lollipop is called with
  107. * Urls as commandline arguments and no instance is running yet
  108. */
  109. private string[] spawn_urls;
  110. /**
  111. * Create a new TrackList
  112. */
  113. public TrackList(TrackListBackground tbl) {
  114. this.add_constraint(
  115. new Clutter.BindConstraint(tbl, Clutter.BindCoordinate.WIDTH,0)
  116. );
  117. this.add_constraint(
  118. new Clutter.AlignConstraint(tbl, Clutter.AlignAxis.Y_AXIS, 0.5f)
  119. );
  120. this.reactive=true;
  121. this.opacity = 0x00;
  122. this.visible = true;
  123. this.transitions_completed.connect(do_transitions_completed);
  124. this.notify["current-track"].connect((d,e)=>{
  125. Application.S().show_web_view(this.current_track);
  126. });
  127. this.boxlayout = new Clutter.BoxLayout();
  128. boxlayout.orientation = Clutter.Orientation.VERTICAL;
  129. this.set_layout_manager(boxlayout);
  130. this.add_empty_track();
  131. }
  132. /**
  133. * Rebuild a tracklist from a JSON
  134. */
  135. public void from_json(Json.Node n){
  136. if (n.get_node_type() != Json.NodeType.ARRAY)
  137. stdout.printf(_("tracklist must be array\n"));
  138. Json.Array arr = n.get_array();
  139. foreach (unowned Json.Node item in arr.get_elements()) {
  140. HistoryTrack t;
  141. try {
  142. t = new HistoryTrack.from_json(this, item);
  143. this.add_track(t);
  144. } catch (HistoryTrackError e) {
  145. stdout.printf(_("track generation failed\n"));
  146. }
  147. }
  148. }
  149. /**
  150. * Returns empty track
  151. */
  152. public EmptyTrack get_empty_track() {
  153. return this.empty_track;
  154. }
  155. /**
  156. * Registers urls to be loaded when the user
  157. * finished deciding wheter to restore an old session or to begin
  158. * a new one
  159. */
  160. public void register_spawn_urls(string[] urls) {
  161. this.spawn_urls = urls;
  162. }
  163. /**
  164. * Load the spawn urls
  165. */
  166. public void spawn() {
  167. if (this.spawn_urls != null) {
  168. foreach (string url in this.spawn_urls) {
  169. this.add_track_with_url(url);
  170. }
  171. this.spawn_urls = null;
  172. }
  173. }
  174. /**
  175. * Serialize this TrackList to JSON
  176. */
  177. public bool to_json(Json.Builder b) {
  178. b.begin_object();
  179. b.set_member_name("tracks");
  180. b.begin_array();
  181. bool valid = false;
  182. foreach (Clutter.Actor child in this.get_children()) {
  183. if (child is HistoryTrack) {
  184. (child as HistoryTrack).to_json(b);
  185. valid = true;
  186. }
  187. }
  188. b.end_array();
  189. b.end_object();
  190. return valid;
  191. }
  192. /**
  193. * Add the given HistoryTrack to this TrackList
  194. */
  195. private void add_track(HistoryTrack t) {
  196. this.insert_child_below(t, this.empty_track);
  197. this.boxlayout.child_set_property(this, t, "x-fill",true);
  198. }
  199. /**
  200. * Get last HistoryTrack
  201. */
  202. public HistoryTrack? get_last_track() {
  203. if (this.last_child == this.first_child) {
  204. return null;
  205. } else {
  206. return this.last_child.get_previous_sibling() as HistoryTrack;
  207. }
  208. }
  209. /**
  210. * Generate a new Track from the given url and add it to this
  211. * Tracklist
  212. */
  213. public void add_track_with_url(string url) {
  214. var t = new HistoryTrack(this, url);
  215. this.add_track(t);
  216. }
  217. /**
  218. * Generate a new Track from the given node and add it to
  219. * this Tracklist.
  220. */
  221. public void add_track_with_node(Node n, SiteNode? current_node, string search_string="") {
  222. var t = new HistoryTrack.with_node(this, (n as SiteNode), current_node, search_string);
  223. this.add_track(t);
  224. }
  225. /**
  226. * Returns the Track that the given Node belongs to.
  227. * Returns null if no Track belongs to the given Node.
  228. */
  229. public Track? get_track_of_node(Node n){
  230. foreach (Clutter.Actor t in this.get_children()) {
  231. if (t is HistoryTrack && (t as HistoryTrack).contains(n)) {
  232. return (t as HistoryTrack);
  233. }
  234. }
  235. return null;
  236. }
  237. /**
  238. * Add an EmptyTrack to this TrackList
  239. */
  240. private void add_empty_track() {
  241. this.empty_track = new EmptyTrack(this);
  242. this.add_child(this.empty_track);
  243. this.boxlayout.child_set_property(this, this.empty_track,"x-fill",true);
  244. }
  245. private void do_transitions_completed() {
  246. if (this.opacity == 0x00) {
  247. this.visible = false;
  248. }
  249. }
  250. /**
  251. * Fade in
  252. */
  253. public void emerge() {
  254. foreach (Clutter.Actor t in this.get_children()){
  255. (t as Track).emerge();
  256. }
  257. this.visible = true;
  258. this.save_easing_state();
  259. this.opacity = 0xE0;
  260. this.restore_easing_state();
  261. }
  262. /**
  263. * Fade out
  264. */
  265. public void disappear() {
  266. foreach (Clutter.Actor t in this.get_children()){
  267. (t as Track).disappear();
  268. }
  269. this.save_easing_state();
  270. this.opacity = 0x00;
  271. this.restore_easing_state();
  272. }
  273. }
  274. }