comparison mde/content/ServiceContent.d @ 173:a1ba9157510e

Enabled ServiceContentList to call its callbacks when its value changes. Tried to fix some other bugs, but this is not a very clean commit, due to wanting to make some big changes to enable better use of invariants next.
author Diggory Hardy <diggory.hardy@gmail.com>
date Sat, 08 Aug 2009 15:53:10 +0200
parents 7f7b2011b759
children 1f9d00f392bd
comparison
equal deleted inserted replaced
172:0dd49f333189 173:a1ba9157510e
23 */ 23 */
24 module mde.content.ServiceContent; 24 module mde.content.ServiceContent;
25 25
26 import mde.content.AStringContent; 26 import mde.content.AStringContent;
27 27
28 debug {
29 import tango.util.log.Log : Log, Logger;
30 private Logger logger;
31 static this () {
32 logger = Log.getLogger ("mde.gui.content.ServiceContent");
33 }
34 }
35
28 /** Interface for ServiceContent and ServiceContentList. */ 36 /** Interface for ServiceContent and ServiceContentList. */
29 interface IServiceContent : IContent { 37 interface IServiceContent : IContent {
30 void setContent (Content cont); 38 void setContent (Content cont);
31 } 39 }
32 40
44 52
45 /** Pass the content this service should prepare for. 53 /** Pass the content this service should prepare for.
46 * 54 *
47 * Stores the reference, because it won't be passed later. */ 55 * Stores the reference, because it won't be passed later. */
48 override void setContent (Content cont) { 56 override void setContent (Content cont) {
57 T oCont = activeCont;
49 activeCont = cast(T)cont; 58 activeCont = cast(T)cont;
59 if ((oCont !is null) != (activeCont !is null))
60 endEvent;
50 } 61 }
51 62
52 override bool opCall () { 63 override bool opCall () {
53 return activeCont is null; 64 debug logger.trace ("ServiceContent.opCall: {}", symbol);
65 return activeCont !is null;
54 } 66 }
55 // Doesn't support directly setting the value 67 // Doesn't support directly setting the value
56 override void opAssign (bool val) {} 68 override void opAssign (bool val) {}
57 69
58 package: 70 package:
70 super (symbol); 82 super (symbol);
71 } 83 }
72 84
73 void setContent (Content cont) { 85 void setContent (Content cont) {
74 foreach (child; list_) { 86 foreach (child; list_) {
75 debug assert (cast(IServiceContent)child !is null);
76 (cast(IServiceContent)child).setContent (cont); 87 (cast(IServiceContent)child).setContent (cont);
77 } 88 }
78 } 89 }
79 90
91 override void append (Content x) {
92 assert (cast(IBoolContent) x, "Only IBoolContent children are allowed!");
93 list_ ~= x;
94 x.addCallback (&childChangeCB);
95 }
96
80 override bool opCall () { 97 override bool opCall () {
81 foreach (child; list_) { 98 debug logger.trace ("ServiceContentList.opCall");
82 debug assert (cast(IBoolContent)child !is null); 99 return v;
83 if (!(cast(IBoolContent)child)())
84 return false;
85 }
86 return true;
87 } 100 }
88 // Doesn't support directly setting the value 101 // Doesn't support directly setting the value
89 override void opAssign (bool val) {} 102 override void opAssign (bool val) {}
90 103
91 104
99 static ServiceContentList createItems (char[] name) { 112 static ServiceContentList createItems (char[] name) {
100 char[] lName = "menus.services."~name; 113 char[] lName = "menus.services."~name;
101 auto ret = new ServiceContentList (lName); 114 auto ret = new ServiceContentList (lName);
102 115
103 // Many use callbacks on a generic class type. For this, we should be sure of the type. 116 // Many use callbacks on a generic class type. For this, we should be sure of the type.
104 (new AStringService(lName~".copy")).addCallback ((IContent c) { 117 (new AStringService(lName~".copy")).addCallback (delegate void(IContent c) {
105 debug assert (cast(AStringService)c); 118 debug assert (cast(AStringService)c);
106 with (cast(AStringService)c) { 119 with (cast(AStringService)c) {
107 if (activeCont !is null) 120 if (activeCont !is null)
108 clipboard = activeCont.toString(0); 121 clipboard = activeCont.toString(0);
109 } 122 }
110 }); 123 });
111 (new AStringService(lName~".paste")).addCallback ((IContent c) { 124 (new AStringService(lName~".paste")).addCallback (delegate void(IContent c) {
112 debug assert (cast(AStringService)c); 125 debug assert (cast(AStringService)c);
113 with (cast(AStringService)c) { 126 with (cast(AStringService)c) {
114 if (activeCont !is null) 127 if (activeCont !is null)
115 activeCont = clipboard; 128 activeCont = clipboard;
116 } 129 }
117 }); 130 });
118 131
119 new ServiceContentList(lName~".calculator"); 132 new ServiceContentList(lName~".calculator");
120 (new IntService(lName~".calculator.increment")).addCallback ((IContent c) { 133 (new IntService(lName~".calculator.increment")).addCallback (delegate void(IContent c) {
121 debug assert (cast(IntService)c); 134 debug assert (cast(IntService)c);
122 with (cast(IntService)c) { 135 with (cast(IntService)c) {
123 if (activeCont !is null) 136 if (activeCont !is null)
124 activeCont = activeCont()+1; 137 activeCont = activeCont()+1;
125 } 138 }
126 }); 139 });
127 (new IntService(lName~".calculator.decrement")).addCallback ((IContent c) { 140 (new IntService(lName~".calculator.decrement")).addCallback (delegate void(IContent c) {
128 debug assert (cast(IntService)c); 141 debug assert (cast(IntService)c);
129 with (cast(IntService)c) { 142 with (cast(IntService)c) {
130 if (activeCont !is null) 143 if (activeCont !is null)
131 activeCont = activeCont()-1; 144 activeCont = activeCont()-1;
132 } 145 }
133 }); 146 });
134 return ret; 147 return ret;
135 } 148 }
136 149
137 private: 150 private:
151 void childChangeCB (IContent icont) {
152 if (v == false) { // then value changes iff icont()
153 debug assert (cast(IBoolContent) icont);
154 if ((cast(IBoolContent) icont)()) {
155 v = true;
156 endEvent;
157 }
158 } else { // we must check all children
159 v = false;
160 foreach (child; list_) {
161 if ((cast(IBoolContent)child)()) {
162 v = true;
163 break;
164 }
165 }
166 if (!v)
167 endEvent;
168 }
169 }
170
171 bool v = false; // cache value so we can see when it changes
138 static char[] clipboard; 172 static char[] clipboard;
139 //TODO: lock on clipboard: static Mutex mutex; 173 //TODO: lock on clipboard: static Mutex mutex;
140 } 174 }