Skip to content
This repository has been archived by the owner on Dec 13, 2023. It is now read-only.

Commit

Permalink
Expose access to GetPropertyChangedSignal (#51)
Browse files Browse the repository at this point in the history
  • Loading branch information
AmaranthineCodices authored and LPGhatguy committed Mar 25, 2018
1 parent 26f0579 commit bbb0663
Show file tree
Hide file tree
Showing 7 changed files with 175 additions and 2 deletions.
23 changes: 23 additions & 0 deletions lib/Change.lua
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
local Change = {}

local changeMetatable = {
__tostring = function(self)
return ("ChangeListener(%s)"):format(self.name)
end
}

setmetatable(Change, {
__index = function(self, propertyName)
local changeListener = {
type = Change,
name = propertyName
}

setmetatable(changeListener, changeMetatable)
Change[propertyName] = changeListener

return changeListener
end,
})

return Change
15 changes: 15 additions & 0 deletions lib/Change.spec.lua
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
return function()
local Change = require(script.Parent.Change)

it("should yield change listener objects when indexed", function()
expect(Change.Text).to.be.ok()
expect(Change.Selected).to.be.ok()
end)

it("should yield the same object when indexed again", function()
local a = Change.Text
local b = Change.Text

expect(a).to.equal(b)
end)
end
5 changes: 4 additions & 1 deletion lib/Reconciler.lua
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,7 @@

local Core = require(script.Parent.Core)
local Event = require(script.Parent.Event)
local Change = require(script.Parent.Change)
local getDefaultPropertyValue = require(script.Parent.getDefaultPropertyValue)
local SingleEventManager = require(script.Parent.SingleEventManager)
local Symbol = require(script.Parent.Symbol)
Expand Down Expand Up @@ -512,6 +513,8 @@ function Reconciler._setRbxProp(rbx, key, value, element)

if key.type == Event then
Reconciler._singleEventManager:connect(rbx, key.name, value)
elseif key.type == Change then
Reconciler._singleEventManager:connectProperty(rbx, key.name, value)
else
local source = element.source or DEFAULT_SOURCE

Expand Down Expand Up @@ -539,4 +542,4 @@ function Reconciler._setRbxProp(rbx, key, value, element)
end
end

return Reconciler
return Reconciler
45 changes: 44 additions & 1 deletion lib/SingleEventManager.lua
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,21 @@ local function createHook(rbx, key, method)
return hook
end

local function createChangeHook(rbx, key, method)
local hook = {
method = method,
connection = rbx:GetPropertyChangedSignal(key):Connect(function(...)
method(rbx, ...)
end)
}

return hook
end

local function formatChangeKey(key)
return ("!PropertyChangeEvent:%s"):format(key)
end

function SingleEventManager.new()
local self = {}

Expand Down Expand Up @@ -64,6 +79,30 @@ function SingleEventManager:connect(rbx, key, method)
end
end

function SingleEventManager:connectProperty(rbx, key, method)
local rbxHooks = self._hookCache[rbx]
local formattedKey = formatChangeKey(key)

if rbxHooks then
local existingHook = rbxHooks[formattedKey]

if existingHook then
if existingHook.method == method then
return
end

existingHook.connection:Disconnect()
end

rbxHooks[formattedKey] = createChangeHook(rbx, key, method)
else
rbxHooks = {}
rbxHooks[formattedKey] = createChangeHook(rbx, key, method)

self._hookCache[rbx] = rbxHooks
end
end

function SingleEventManager:disconnect(rbx, key)
local rbxHooks = self._hookCache[rbx]

Expand All @@ -85,6 +124,10 @@ function SingleEventManager:disconnect(rbx, key)
end
end

function SingleEventManager:disconnectProperty(rbx, key)
self:disconnect(rbx, formatChangeKey(key))
end

function SingleEventManager:disconnectAll(rbx)
local rbxHooks = self._hookCache[rbx]

Expand All @@ -99,4 +142,4 @@ function SingleEventManager:disconnectAll(rbx)
self._hookCache[rbx] = nil
end

return SingleEventManager
return SingleEventManager
86 changes: 86 additions & 0 deletions lib/SingleEventManager.spec.lua
Original file line number Diff line number Diff line change
Expand Up @@ -83,6 +83,57 @@ return function()
end)
end)

describe("connectProperty", function()
it("should connect to property changes", function()
local target = Instance.new("BindableEvent")
local manager = SingleEventManager.new()

local changeCount = 0

manager:connectProperty(target, "Name", function(rbx)
changeCount = changeCount + 1
end)

target.Name = "hi"
expect(changeCount).to.equal(1)
end)

it("should disconnect the existing connection if present", function()
local target = Instance.new("IntValue")
local manager = SingleEventManager.new()

local changeCountA = 0
local changeCountB = 0

manager:connectProperty(target, "Name", function(rbx)
changeCountA = changeCountA + 1
end)

manager:connectProperty(target, "Name", function(rbx)
changeCountB = changeCountB + 1
end)

target.Name = "hi"
expect(changeCountA).to.equal(0)
expect(changeCountB).to.equal(1)
end)

it("should only connect to the property specified", function()
local target = Instance.new("IntValue")
local manager = SingleEventManager.new()

local changeCount = 0

manager:connectProperty(target, "Name", function(rbx)
changeCount = changeCount + 1
end)

target.Name = "hi"
target.Value = 0
expect(changeCount).to.equal(1)
end)
end)

describe("disconnect", function()
it("should disconnect handlers on an object", function()
local target = Instance.new("BindableEvent")
Expand Down Expand Up @@ -146,13 +197,41 @@ return function()
end)
end)

describe("disconnectProperty", function()
it("should disconnect property change handlers on an object", function()
local target = Instance.new("IntValue")
local manager = SingleEventManager.new()

local changeCount = 0

manager:connectProperty(target, "Name", function(rbx)
changeCount = changeCount + 1
end)

target.Name = "hi"
expect(changeCount).to.equal(1)

manager:disconnectProperty(target, "Name")
target.Name = "test"
expect(changeCount).to.equal(1)
end)

it("should succeed even if no handler is attached", function()
local target = Instance.new("IntValue")
local manager = SingleEventManager.new()

manager:disconnectProperty(target, "Name")
end)
end)

describe("disconnectAll", function()
it("should disconnect all listeners on an object", function()
local target = Instance.new("BindableEvent")
local manager = SingleEventManager.new()

local callCountEvent = 0
local callCountChanged = 0
local changeCount = 0

manager:connect(target, "Event", function(rbx)
expect(rbx).to.equal(target)
Expand All @@ -164,11 +243,17 @@ return function()
callCountChanged = callCountChanged + 1
end)

manager:connectProperty(target, "Name", function(rbx)
expect(rbx).to.equal(target)
changeCount = changeCount + 1
end)

target:Fire()
target.Name = "bar"

expect(callCountEvent).to.equal(1)
expect(callCountChanged).to.equal(1)
expect(changeCount).to.equal(1)

manager:disconnectAll(target)

Expand All @@ -177,6 +262,7 @@ return function()

expect(callCountEvent).to.equal(1)
expect(callCountChanged).to.equal(1)
expect(changeCount).to.equal(1)
end)

it("should succeed with no events attached", function()
Expand Down
2 changes: 2 additions & 0 deletions lib/init.lua
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@
local Component = require(script.Component)
local Core = require(script.Core)
local Event = require(script.Event)
local Change = require(script.Change)
local GlobalConfig = require(script.GlobalConfig)
local PureComponent = require(script.PureComponent)
local Reconciler = require(script.Reconciler)
Expand Down Expand Up @@ -37,6 +38,7 @@ apply(Roact, {
Component = Component,
PureComponent = PureComponent,
Event = Event,
Change = Change,
})

apply(Roact, {
Expand Down
1 change: 1 addition & 0 deletions lib/init.spec.lua
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@ return function()
expect(Roact.Portal).to.be.ok()
expect(Roact.Children).to.be.ok()
expect(Roact.Event).to.be.ok()
expect(Roact.Change).to.be.ok()
expect(Roact.Ref).to.be.ok()
expect(Roact.None).to.be.ok()
end)
Expand Down

0 comments on commit bbb0663

Please sign in to comment.