Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Added content-sensitive settings: status, first interval, interval #8

Merged
merged 1 commit into from
Apr 22, 2016
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
26 changes: 25 additions & 1 deletion src/MicroflowTimer/MicroflowTimer.xml
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@
<icon></icon>

<properties>
<property key="interval" type="integer" defaultValue="30000">
<property key="interval" type="integer" defaultValue="30000">
<caption>Interval (in ms)</caption>
<category>Behavior</category>
<description>
Expand All @@ -29,6 +29,30 @@
<description>The microflow to be executed. If the microflow returns false, it will not be executed any longer until the context changes.</description>
<returnType type="Boolean" />
</property>
<property key="firstIntervalAttr" type="attribute" required="false">
<caption>First tick delay</caption>
<category>Context</category>
<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>
<attributeTypes>
<attributeType name="Integer" />
</attributeTypes>
</property>
<property key="intervalAttr" type="attribute" required="false">
<caption>Interval Attribute (in ms)</caption>
<category>Context</category>
<description>Defines how often the microflow is called using an attribute. If set, overrides the interval specified below.</description>
<attributeTypes>
<attributeType name="Integer" />
</attributeTypes>
</property>
<property key="timerStatusAttr" type="attribute" required="false">
<caption>Timer Status Attribute</caption>
<category>Context</category>
<description>An optional attribute on the context entity, indicating the status of the timer.</description>
<attributeTypes>
<attributeType name="Boolean" />
</attributeTypes>
</property>
</properties>
</widget>

169 changes: 157 additions & 12 deletions src/MicroflowTimer/widget/MicroflowTimer.js
Original file line number Diff line number Diff line change
Expand Up @@ -13,19 +13,37 @@ require([
once: false,
startatonce: true,
microflow: "",
firstIntervalAttr: null,
intervalAttr: null,
timerStatusAttr: null,


// Internal variables. Non-primitives created in the prototype are shared between all widget instances.
_handle: null,
_handles: null,
_contextObj: null,
_timer: null,
_timeout: null,
_timerStarted: false,

postcreate: function() {
// Uncomment the following line to enable debug messages
logger.level(logger.DEBUG);

this._handles = [];
},

update: function (obj, callback) {
logger.debug(this.id + ".update");

this._contextObj = obj;
if (!this._timerStarted) {
this._resetSubscriptions();

//changes the interval to the attribute value, if set
if (this._contextObj && this.intervalAttr) {
this.interval = this._contextObj.get(this.intervalAttr);
}

if (!this._timerStarted) {
this._runTimer();
}

Expand All @@ -38,24 +56,105 @@ require([
this._stopTimer();
},

_checkTimerStatus: function () {
logger.debug(this.id + "._checkStatus");

//both optional attributes are used
if (this.intervalAttr && this.timerStatusAttr) {
//get the running state
var running = this._contextObj.get(this.timerStatusAttr);
//change the interval if it was set in the attribute
var newInterval = this._contextObj.get(this.intervalAttr);
if (this.interval !== newInterval) {
this.interval = newInterval;
//stop and start the timer if it's running and will keep running
if (running && this._timerStarted) {
this._intervalChange(newInterval);
}
}

this._timerStatusChange(running);

//just timer status is used
} else if (this.timerStatusAttr) {
var running = this._contextObj.get(this.timerStatusAttr);
this._timerStatusChange(running);

//just interval is used
} else if (this.intervalAttr) {
var newInterval = this._contextObj.get(this.intervalAttr);
if (this.interval !== newInterval) {
this.interval = newInterval;
this._intervalChange(newInterval);

}
}

},

_timerStatusChange(running) {
if (running !== this._timerStarted) {
if (running) {
this._runTimer();
} else {
this._stopTimer();
}

}
},

//Called when the optional timer interval attribute is changed
_intervalChange: function (newInterval) {
logger.debug(this.id + "._intervalChange");

this.interval = newInterval;

if (this._timerStarted) {
this._stopTimer();
this._runTimer();
}

},

_runTimer: function () {
logger.debug(this.id + "._runTimer", this.interval);
if (this.microflow !== "" && this._contextObj) {
this._timerStarted = true;
if (this.once) {
this._timeout = setTimeout(lang.hitch(this, this._execMf), this.interval);
} else {
if (this.startatonce) {
this._execMf();
}
this._timer = setInterval(lang.hitch(this, this._execMf), this.interval);
}

//if there's a first interval, get and use that first, then use the regular interval
if(this.firstIntervalAttr) {
var firstInterval = this._contextObj.get(this.firstIntervalAttr);

if (this.once) {
this._timeout = setTimeout(lang.hitch(this, this._execMf), firstInterval);
} else {
if (this.startatonce) {
this._execMf();
}
this._timeout = setTimeout(lang.hitch(this, function() {
this._execMf();
this._timer = setInterval(lang.hitch(this, this._execMf), this.interval);
}), firstInterval);
}
//otherwise just use the regulat interval
} else {
if (this.once) {
this._timeout = setTimeout(lang.hitch(this, this._execMf), this.interval);
} else {
if (this.startatonce) {
this._execMf();
}
this._timer = setInterval(lang.hitch(this, this._execMf), this.interval);
}
}
}
},

_stopTimer: function () {
logger.debug(this.id + "._stopTimer");
if (this._timer !== null) {
this._timerStarted = false;

if (this._timer !== null) {
logger.debug(this.id + "._stopTimer timer cleared");
clearInterval(this._timer);
this._timer = null;
Expand Down Expand Up @@ -91,6 +190,52 @@ require([
}
});
}
},

// Reset subscriptions.
_resetSubscriptions: function () {
var _objectHandle = null,
_attrHandle = null,
_attrHandle2 = null;

// Release handles on previous object, if any.
if (this._handles) {
dojoArray.forEach(this._handles, function(handle, i){
mx.data.unsubscribe(handle);
});

this._handles = [];
}

// When a mendix object exists create subscribtions.
if (this._contextObj && this.timerStatusAttr) {
_objectHandle = this.subscribe({
guid: this._contextObj.getGuid(),
callback: lang.hitch(this, function (guid) {
this._checkTimerStatus();
})
});

_attrHandle = this.subscribe({
guid: this._contextObj.getGuid(),
attr: this.timerStatusAttr,
callback: lang.hitch(this, function(guid, attr, attrValue) {
this._checkTimerStatus();
})
});

_attrHandle2 = this.subscribe({
guid: this._contextObj.getGuid(),
attr: this.intervalAttr,
callback: lang.hitch(this, function(guid, attr, attrValue) {
this._intervalChange();
})
});

this._handles = [_objectHandle, _attrHandle, _attrHandle2];

}
}

});
});
Binary file modified test/Test.mpr
Binary file not shown.
Binary file modified test/widgets/MicroflowTimer.mpk
Binary file not shown.