Skip to content

Commit 010ef76

Browse files
committed
Merge pull request #8 from tieniber/master
Added content-sensitive settings: status, first interval, interval
2 parents afca768 + 7030a55 commit 010ef76

File tree

4 files changed

+182
-13
lines changed

4 files changed

+182
-13
lines changed

src/MicroflowTimer/MicroflowTimer.xml

Lines changed: 25 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,7 @@
66
<icon></icon>
77

88
<properties>
9-
<property key="interval" type="integer" defaultValue="30000">
9+
<property key="interval" type="integer" defaultValue="30000">
1010
<caption>Interval (in ms)</caption>
1111
<category>Behavior</category>
1212
<description>
@@ -29,6 +29,30 @@
2929
<description>The microflow to be executed. If the microflow returns false, it will not be executed any longer until the context changes.</description>
3030
<returnType type="Boolean" />
3131
</property>
32+
<property key="firstIntervalAttr" type="attribute" required="false">
33+
<caption>First tick delay</caption>
34+
<category>Context</category>
35+
<description>An optional attribute on the context entity, indicating a custom first interval (in milliseconds). This could be used for continuing a timer that ticks once per minute, but should wait for 60 seconds thereafter.</description>
36+
<attributeTypes>
37+
<attributeType name="Integer" />
38+
</attributeTypes>
39+
</property>
40+
<property key="intervalAttr" type="attribute" required="false">
41+
<caption>Interval Attribute (in ms)</caption>
42+
<category>Context</category>
43+
<description>Defines how often the microflow is called using an attribute. If set, overrides the interval specified below.</description>
44+
<attributeTypes>
45+
<attributeType name="Integer" />
46+
</attributeTypes>
47+
</property>
48+
<property key="timerStatusAttr" type="attribute" required="false">
49+
<caption>Timer Status Attribute</caption>
50+
<category>Context</category>
51+
<description>An optional attribute on the context entity, indicating the status of the timer.</description>
52+
<attributeTypes>
53+
<attributeType name="Boolean" />
54+
</attributeTypes>
55+
</property>
3256
</properties>
3357
</widget>
3458

src/MicroflowTimer/widget/MicroflowTimer.js

Lines changed: 157 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -13,19 +13,37 @@ require([
1313
once: false,
1414
startatonce: true,
1515
microflow: "",
16+
firstIntervalAttr: null,
17+
intervalAttr: null,
18+
timerStatusAttr: null,
19+
1620

1721
// Internal variables. Non-primitives created in the prototype are shared between all widget instances.
18-
_handle: null,
22+
_handles: null,
1923
_contextObj: null,
2024
_timer: null,
2125
_timeout: null,
2226
_timerStarted: false,
2327

28+
postcreate: function() {
29+
// Uncomment the following line to enable debug messages
30+
logger.level(logger.DEBUG);
31+
32+
this._handles = [];
33+
},
34+
2435
update: function (obj, callback) {
2536
logger.debug(this.id + ".update");
26-
37+
2738
this._contextObj = obj;
28-
if (!this._timerStarted) {
39+
this._resetSubscriptions();
40+
41+
//changes the interval to the attribute value, if set
42+
if (this._contextObj && this.intervalAttr) {
43+
this.interval = this._contextObj.get(this.intervalAttr);
44+
}
45+
46+
if (!this._timerStarted) {
2947
this._runTimer();
3048
}
3149

@@ -38,24 +56,105 @@ require([
3856
this._stopTimer();
3957
},
4058

59+
_checkTimerStatus: function () {
60+
logger.debug(this.id + "._checkStatus");
61+
62+
//both optional attributes are used
63+
if (this.intervalAttr && this.timerStatusAttr) {
64+
//get the running state
65+
var running = this._contextObj.get(this.timerStatusAttr);
66+
//change the interval if it was set in the attribute
67+
var newInterval = this._contextObj.get(this.intervalAttr);
68+
if (this.interval !== newInterval) {
69+
this.interval = newInterval;
70+
//stop and start the timer if it's running and will keep running
71+
if (running && this._timerStarted) {
72+
this._intervalChange(newInterval);
73+
}
74+
}
75+
76+
this._timerStatusChange(running);
77+
78+
//just timer status is used
79+
} else if (this.timerStatusAttr) {
80+
var running = this._contextObj.get(this.timerStatusAttr);
81+
this._timerStatusChange(running);
82+
83+
//just interval is used
84+
} else if (this.intervalAttr) {
85+
var newInterval = this._contextObj.get(this.intervalAttr);
86+
if (this.interval !== newInterval) {
87+
this.interval = newInterval;
88+
this._intervalChange(newInterval);
89+
90+
}
91+
}
92+
93+
},
94+
95+
_timerStatusChange(running) {
96+
if (running !== this._timerStarted) {
97+
if (running) {
98+
this._runTimer();
99+
} else {
100+
this._stopTimer();
101+
}
102+
103+
}
104+
},
105+
106+
//Called when the optional timer interval attribute is changed
107+
_intervalChange: function (newInterval) {
108+
logger.debug(this.id + "._intervalChange");
109+
110+
this.interval = newInterval;
111+
112+
if (this._timerStarted) {
113+
this._stopTimer();
114+
this._runTimer();
115+
}
116+
117+
},
118+
41119
_runTimer: function () {
42120
logger.debug(this.id + "._runTimer", this.interval);
43121
if (this.microflow !== "" && this._contextObj) {
44122
this._timerStarted = true;
45-
if (this.once) {
46-
this._timeout = setTimeout(lang.hitch(this, this._execMf), this.interval);
47-
} else {
48-
if (this.startatonce) {
49-
this._execMf();
50-
}
51-
this._timer = setInterval(lang.hitch(this, this._execMf), this.interval);
52-
}
123+
124+
//if there's a first interval, get and use that first, then use the regular interval
125+
if(this.firstIntervalAttr) {
126+
var firstInterval = this._contextObj.get(this.firstIntervalAttr);
127+
128+
if (this.once) {
129+
this._timeout = setTimeout(lang.hitch(this, this._execMf), firstInterval);
130+
} else {
131+
if (this.startatonce) {
132+
this._execMf();
133+
}
134+
this._timeout = setTimeout(lang.hitch(this, function() {
135+
this._execMf();
136+
this._timer = setInterval(lang.hitch(this, this._execMf), this.interval);
137+
}), firstInterval);
138+
}
139+
//otherwise just use the regulat interval
140+
} else {
141+
if (this.once) {
142+
this._timeout = setTimeout(lang.hitch(this, this._execMf), this.interval);
143+
} else {
144+
if (this.startatonce) {
145+
this._execMf();
146+
}
147+
this._timer = setInterval(lang.hitch(this, this._execMf), this.interval);
148+
}
149+
}
53150
}
54151
},
55152

56153
_stopTimer: function () {
57154
logger.debug(this.id + "._stopTimer");
58-
if (this._timer !== null) {
155+
this._timerStarted = false;
156+
157+
if (this._timer !== null) {
59158
logger.debug(this.id + "._stopTimer timer cleared");
60159
clearInterval(this._timer);
61160
this._timer = null;
@@ -91,6 +190,52 @@ require([
91190
}
92191
});
93192
}
193+
},
194+
195+
// Reset subscriptions.
196+
_resetSubscriptions: function () {
197+
var _objectHandle = null,
198+
_attrHandle = null,
199+
_attrHandle2 = null;
200+
201+
// Release handles on previous object, if any.
202+
if (this._handles) {
203+
dojoArray.forEach(this._handles, function(handle, i){
204+
mx.data.unsubscribe(handle);
205+
});
206+
207+
this._handles = [];
208+
}
209+
210+
// When a mendix object exists create subscribtions.
211+
if (this._contextObj && this.timerStatusAttr) {
212+
_objectHandle = this.subscribe({
213+
guid: this._contextObj.getGuid(),
214+
callback: lang.hitch(this, function (guid) {
215+
this._checkTimerStatus();
216+
})
217+
});
218+
219+
_attrHandle = this.subscribe({
220+
guid: this._contextObj.getGuid(),
221+
attr: this.timerStatusAttr,
222+
callback: lang.hitch(this, function(guid, attr, attrValue) {
223+
this._checkTimerStatus();
224+
})
225+
});
226+
227+
_attrHandle2 = this.subscribe({
228+
guid: this._contextObj.getGuid(),
229+
attr: this.intervalAttr,
230+
callback: lang.hitch(this, function(guid, attr, attrValue) {
231+
this._intervalChange();
232+
})
233+
});
234+
235+
this._handles = [_objectHandle, _attrHandle, _attrHandle2];
236+
237+
}
94238
}
239+
95240
});
96241
});

test/Test.mpr

85 KB
Binary file not shown.

test/widgets/MicroflowTimer.mpk

1.38 KB
Binary file not shown.

0 commit comments

Comments
 (0)