-
Notifications
You must be signed in to change notification settings - Fork 26
/
block_limits.js
131 lines (115 loc) · 3.11 KB
/
block_limits.js
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
/**
* @fileoverview Block Limits helper class for managing limited
* quantities of blocks within a flyout
*/
'use strict';
goog.provide('Blockly.BlockLimits');
goog.require('Blockly.Block');
/**
* @typedef {Object} BlockLimit
* @property {number} count
* @property {number} limit
*/
/**
* Class for managing block limits
* @constructor
*/
Blockly.BlockLimits = function() {
/**
* Store of block types to block limit tracking objects.
* {Object.<string, BlockLimit>}
* @private
*/
this.limits_ = {};
/**
* Fires event 'change' on remaining block count change.
* @type {goog.events.EventTarget}
*/
this.events = new goog.events.EventTarget();
};
Blockly.BlockLimits.prototype.setLimit = function(type, limit) {
this.limits_[type] = {
count: undefined,
limit: limit
};
this.updateCount(type, 0);
};
/**
* Update the block counts for limited-quantity workspace blocks
* @param {string[]} blockTypes
*/
Blockly.BlockLimits.prototype.updateBlockTotals = function(blockTypes) {
var countsByType = Blockly.aggregateCounts(blockTypes);
goog.object.forEach(
this.limits_,
function(limit, type) {
var blockCount = countsByType[type] || 0;
this.updateCount(type, blockCount);
}.bind(this)
);
};
Blockly.BlockLimits.prototype.updateCount = function(type, newCount) {
var limit = this.limits_[type];
var countChanged = newCount !== limit.count;
limit.count = newCount;
if (countChanged) {
this.events.fireListeners('change', false, {
type: type,
limit: limit.limit,
remaining: limit.limit - limit.count
});
}
};
Blockly.BlockLimits.prototype.getLimit = function(type) {
return this.limits_[type] ? this.limits_[type].limit : undefined;
};
/**
* Returns true iff any of the blocks in this flyout are limited in quantity
* @return {boolean}
*/
Blockly.BlockLimits.prototype.hasBlockLimits = function() {
return Object.keys(this.limits_).length > 0;
};
/**
* Returns true iff all given blocks can be added to this space without
* exceeding any block limits
* @param {string[]} blockTypes
* @return {boolean}
*/
Blockly.BlockLimits.prototype.canAddBlocks = function(blockTypes) {
var countsByType = Blockly.aggregateCounts(blockTypes);
var allWithinLimits = goog.object.every(
countsByType,
function(count, type) {
return this.blockTypeWithinLimits(type, count);
},
this
);
return allWithinLimits;
};
/**
* Returns true if the specified count of the specified block type can
* be added to this space without exceeding any block limits
* @param {string} type
* @param {number} count
* @return {boolean}
*/
Blockly.BlockLimits.prototype.blockTypeWithinLimits = function(type, count) {
if (count === undefined) {
count = 1;
}
var limit = this.limits_[type];
if (limit) {
var remaining = limit.limit - limit.count;
return remaining >= count;
}
return true;
};
/**
* Returns true if any block limit is currently exceeded
*/
Blockly.BlockLimits.prototype.blockLimitExceeded = function() {
return goog.object.findKey(this.limits_, function(value) {
return value.count > value.limit;
});
};