DockPlaceholder.cs 6.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299
  1. /*
  2. * $Id$
  3. *
  4. * Copyright (C) 2004 Todd Berman <tberman@off.net>
  5. * Copyright (C) 2004 Jeroen Zwartepoorte <jeroen@xs4all.nl>
  6. * Copyright (C) 2005 John Luke <john.luke@gmail.com>
  7. *
  8. * based on work by:
  9. * Copyright (C) 2002 Gustavo Giráldez <gustavo.giraldez@gmx.net>
  10. *
  11. * This program is free software; you can redistribute it and/or modify
  12. * it under the terms of the GNU General Public License as published by
  13. * the Free Software Foundation; either version 2 of the License, or
  14. * (at your option) any later version.
  15. *
  16. * This program is distributed in the hope that it will be useful,
  17. * but WITHOUT ANY WARRANTY; without even the implied warranty of
  18. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  19. * GNU General Public License for more details.
  20. *
  21. * You should have received a copy of the GNU General Public License
  22. * along with this program; if not, write to the Free Software
  23. * Foundation, Inc., 59 Temple Place - Suite 330,
  24. * Boston, MA 02111-1307, USA.
  25. */
  26. using System;
  27. using System.Collections;
  28. using System.Xml;
  29. using Gtk;
  30. namespace Gdl
  31. {
  32. public class DockPlaceholder : DockObject
  33. {
  34. private DockObject host;
  35. private bool sticky;
  36. private Stack placementStack;
  37. protected DockPlaceholder (IntPtr raw) : base (raw) { }
  38. public DockPlaceholder (string name, DockObject obj,
  39. DockPlacement position, bool sticky)
  40. {
  41. WidgetFlags |= WidgetFlags.NoWindow;
  42. WidgetFlags &= ~(WidgetFlags.CanFocus);
  43. Sticky = sticky;
  44. Name = name;
  45. if (obj != null) {
  46. Attach (obj);
  47. if (position == DockPlacement.None)
  48. position = DockPlacement.Center;
  49. NextPlacement = position;
  50. //the top placement will be consumed by the toplevel dock, so add a dummy placement
  51. if (obj is Dock)
  52. NextPlacement = DockPlacement.Center;
  53. // try a recursion
  54. DoExcursion ();
  55. }
  56. }
  57. public DockPlaceholder (DockObject obj, bool sticky) :
  58. this (obj.Name, obj, DockPlacement.None, sticky) { }
  59. public DockObject Host {
  60. get {
  61. return host;
  62. }
  63. set {
  64. Attach (value);
  65. EmitPropertyEvent ("Host");
  66. }
  67. }
  68. [After]
  69. [Export]
  70. public DockPlacement NextPlacement {
  71. get {
  72. if (placementStack != null && placementStack.Count > 0)
  73. return (DockPlacement) placementStack.Pop ();
  74. return DockPlacement.Center;
  75. }
  76. set {
  77. if (placementStack == null)
  78. placementStack = new Stack ();
  79. placementStack.Push (value);
  80. }
  81. }
  82. public bool Sticky {
  83. get {
  84. return sticky;
  85. }
  86. set {
  87. sticky = value;
  88. EmitPropertyEvent ("Sticky");
  89. }
  90. }
  91. protected override void OnDestroyed ()
  92. {
  93. if (host != null)
  94. OnDetached (false);
  95. base.OnDestroyed ();
  96. }
  97. protected override void OnAdded (Widget widget)
  98. {
  99. if (!(widget is DockItem))
  100. return;
  101. Dock ((DockItem)widget, NextPlacement, null);
  102. }
  103. public override void OnDetached (bool recursive)
  104. {
  105. // disconnect handlers
  106. DisconnectHost ();
  107. // free the placement stack
  108. placementStack = null;
  109. DockObjectFlags &= ~(DockObjectFlags.Attached);
  110. }
  111. public override void OnReduce ()
  112. {
  113. // placeholders are not reduced
  114. }
  115. public override void OnDocked (DockObject requestor, DockPlacement position, object data)
  116. {
  117. if (host != null) {
  118. // we simply act as a placeholder for our host
  119. host.Dock (requestor, position, data);
  120. } else {
  121. if (!IsBound) {
  122. Console.WriteLine ("Attempt to dock a dock object to an unbound placeholder");
  123. return;
  124. }
  125. // dock the item as a floating of the controller
  126. Master.Controller.Dock (requestor, DockPlacement.Floating, null);
  127. }
  128. }
  129. public override void OnPresent (DockObject child)
  130. {
  131. // do nothing
  132. }
  133. /*
  134. * Tries to shrink the placement stack by examining the host's
  135. * children and see if any of them matches the placement which is at
  136. * the top of the stack. If this is the case, it tries again with the
  137. * new host.
  138. */
  139. public void DoExcursion ()
  140. {
  141. if (host != null && !Sticky && placementStack != null && placementStack.Count > 0 && host.IsCompound) {
  142. DockPlacement pos;
  143. DockPlacement stack_pos = NextPlacement;
  144. foreach (Widget child in host.Children) {
  145. DockObject item = child as DockObject;
  146. if (item == null)
  147. continue;
  148. pos = stack_pos;
  149. host.ChildPlacement (item, ref pos);
  150. if (pos == stack_pos) {
  151. // remove the stack position
  152. if (placementStack.Count > 1)
  153. placementStack.Pop ();
  154. DisconnectHost ();
  155. // connect to the new host
  156. ConnectHost (item);
  157. // recurse ...
  158. if (!item.InReflow)
  159. DoExcursion ();
  160. break;
  161. }
  162. }
  163. }
  164. }
  165. private void DisconnectHost ()
  166. {
  167. if (host == null)
  168. return;
  169. host.Detached -= new DetachedHandler (OnHostDetached);
  170. host.Docked -= new DockedHandler (OnHostDocked);
  171. host = null;
  172. }
  173. private void ConnectHost (DockObject newHost)
  174. {
  175. if (host != null)
  176. DisconnectHost ();
  177. host = newHost;
  178. host.Detached += new DetachedHandler (OnHostDetached);
  179. host.Docked += new DockedHandler (OnHostDocked);
  180. }
  181. public void Attach (DockObject objekt)
  182. {
  183. if (objekt == null)
  184. return;
  185. // object binding
  186. if (!IsBound)
  187. Bind(objekt.Master);
  188. if (objekt.Master != Master)
  189. return;
  190. Freeze ();
  191. // detach from previous host first
  192. if (host != null)
  193. Detach (false);
  194. ConnectHost (objekt);
  195. DockObjectFlags |= DockObjectFlags.Attached;
  196. Thaw ();
  197. }
  198. void OnHostDetached (object sender, DetachedArgs a)
  199. {
  200. // skip sticky objects
  201. if (sticky)
  202. return;
  203. // go up in the hierarchy
  204. DockObject newHost = host.ParentObject;
  205. while (newHost != null) {
  206. DockPlacement pos = DockPlacement.None;
  207. // get a placement hint from the new host
  208. if (newHost.ChildPlacement (host, ref pos))
  209. NextPlacement = pos;
  210. else
  211. Console.WriteLine ("Something weird happened while getting the child placement for {0} from parent {1}", host, newHost);
  212. // we found a "stable" dock object
  213. if (newHost.InDetach)
  214. break;
  215. newHost = newHost.ParentObject;
  216. }
  217. // disconnect host
  218. DisconnectHost ();
  219. // the toplevel was detached: we attach ourselves to the
  220. // controller with an initial placement of floating
  221. if (newHost == null) {
  222. newHost = this.Master.Controller;
  223. NextPlacement = DockPlacement.Floating;
  224. }
  225. if (newHost != null)
  226. ConnectHost (newHost);
  227. PrintPlacementStack ();
  228. }
  229. void OnHostDocked (object sender, DockedArgs a)
  230. {
  231. DockObject obj = sender as DockObject;
  232. // see if the given position is compatible for the stack's top element
  233. if (!sticky && placementStack != null) {
  234. DockPlacement pos = NextPlacement;
  235. if (obj.ChildPlacement (a.Requestor, ref pos))
  236. DoExcursion ();
  237. }
  238. PrintPlacementStack ();
  239. }
  240. [System.Diagnostics.Conditional ("DEBUG")]
  241. void PrintPlacementStack ()
  242. {
  243. }
  244. }
  245. }