-- This class contains methods that are in common between Bars and Groups (and the Manager).
Node = class(Turbine.UI.Window);
function Node:IsHidden()
return (self.settings.hidden or self:IsParentHidden());
end
function Node:IsParentHidden()
return self.parent and self.parent:IsHidden();
end
function Node:SetHidden(hide)
if (self.settings.hidden ~= hide) then
if (self.Log) then
if (hide) then
DoCallbacks(self, "Log", {"hiding", string.upper(self.settings.type)});
else
DoCallbacks(self, "Log", {"showing", string.upper(self.settings.type)});
end
end
self.settings.hidden = hide;
self:ApplyHiddenness();
self:SaveSettings(true);
if (self.HiddenChanged) then
self:HiddenChanged();
end
end
end
function Node:SaveSettings(updateBarDirectory, updateEventDirectory)
if (not self.constructing) then
self.parent:SaveSettings(updateBarDirectory, updateEventDirectory);
end
end
function Node:EditColor()
if (self.colorPicker == nil) then
self.previousColor = self.color;
self.colorPicker = Thurallor.UI.ColorPicker(self.color, "H");
self.colorPicker:SetZOrder(self:GetZOrder() + 10);
self.colorPicker.ColorChanged = function(picker)
self:SetColor(picker:GetColor());
end
self.colorPicker.Accepted = function()
self.colorPicker = nil;
self:SaveSettings(true);
end
self.colorPicker.Canceled = function()
self:SetColor(self.previousColor);
self.colorPicker = nil;
end
end
end
function Node:SetColor(color)
self.color = color;
self.settings.color = color:GetHex();
self:SaveSettings(true, true);
end
function Node:GetID()
return self.objectID;
end
function Node:GetName()
return self.settings.caption.text;
end
function Node:SetName(newName)
self.settings.caption.text = newName;
self:SaveSettings(true, true);
end
function Node:SetCaptionSize(width, height)
self.settings.caption.width = width;
self.settings.caption.height = height;
self:SaveSettings(false);
end
function Node:GetColor()
return self.color;
end
function Node:SetWantsEvents(enable)
local userEventsWanted = {};
local mgrEventCallbacks = self.manager:GetEventCallbacks();
for h = 1, #self.settings.eventHandlers, 1 do
local handler = self.settings.eventHandlers[h];
local object = loadstring("self = ...; return " .. handler.object)(self);
local trigger = handler.trigger;
if (enable) then
-- Should save this function reference as handler.func, so we can pass the same reference to RemoveCallback().
local funcBody = loadstring(handler.action);
handler.func = function(sender, args)
if (self.Log) then
DoCallbacks(self, "Log", {"received: " .. handler.trigger, "EVENT", true});
DoCallbacks(self, "Log", {"behaviour: " .. handler.description, "EVENT"});
end
funcBody(self, object, trigger, args);
end;
--Puts("Node " .. Serialize(self.settings.caption.text) .. ": Compiled handler.action = " .. Serialize(handler.action) .. " into " .. Serialize(handler.func));
--Puts("Node " .. Serialize(self.settings.caption.text) .. ": Registering event handler " .. Serialize(handler.description) .. " (" .. Serialize(handler.func) .. ")");
AddCallback(object, trigger, handler.func);
-- Make a list of user events we're listening for
if (object == mgrEventCallbacks) then
userEventsWanted[trigger] = true;
end
else
--Puts("Node " .. Serialize(self.settings.caption.text) .. ": Unregistering event handler: " .. Serialize(handler.description) .. " (" .. Serialize(handler.func) .. ")");
RemoveCallback(object, trigger, handler.func);
handler.func = nil;
end
end
-- A central list of all user events being listened for is maintained by Manager
self.manager:SetEventListeners(enable, self, userEventsWanted);
end
function Node:RenameUserEvent(oldName, newName)
self:SetWantsEvents(false);
-- Update event handlers
for _, handler in pairs(self.settings.eventHandlers) do
if ((handler.trigger == oldName) and (handler.object == "self.manager:GetEventCallbacks()")) then
handler.trigger = newName;
local oldStr = handler.description;
handler.description = oldStr:sub(1, oldStr:len() - oldName:len()) .. newName;
end
end
self:SetWantsEvents(true);
end
function Node:AddEventHandler(trigger, action, argValue, argName)
self:SetWantsEvents(false);
local prevContext = L:SetContext("/EventBehaviorsMenu");
local description = { action = L:GetText("Actions/" .. action); trigger = L:GetText("Triggers/" .. trigger) };
-- Initialize action
local handler = {};
if ((action == "ShowGroup") or (action == "ShowBar")) then
handler.action = "self:SetHidden(false); ";
elseif ((action == "HideGroup") or (action == "HideBar")) then
handler.action = "self:SetHidden(true); ";
elseif ((action == "ResetGroup") or (action == "ResetBar")) then
handler.action = "self:Reset(); ";
elseif (action == "MoveToCursor") then
handler.action = "self:MoveToMouseCursor(); ";
elseif ((action == "ExpandGroup") or (action == "ExpandBar")) then
handler.action = "self:Expand(); ";
elseif ((action == "CollapseGroup") or (action == "CollapseBar")) then
handler.action = "self:Collapse(); ";
elseif (action == "StopExecuting") then
handler.action = "self:StopExecuting(); ";
elseif (action == "StartExecuting") then
handler.action = "self:StartExecuting(); ";
elseif ((action == "SetGroupTransparency") or (action == "SetTransparency")) then
handler.action = "self:SetTransparency(" .. argValue .. "); ";
description.action = description.action .. " " .. argName;
else
error("Unknown event handler action: " .. tostring(action), 2);
end
-- Add object, trigger, action, description
if (trigger == "AtStartup") then
handler.object = "self.manager:GetEventCallbacks()";
handler.trigger = "Startup\n"; -- includes "\n" so it can't be generated by user
handler.action =
"self = ...; " ..
handler.action;
elseif (trigger == "WhenTargetChanges") then
handler.object = "self.manager.watcher";
handler.trigger = "PlayerTargetChanged";
handler.action =
"self = ...; " ..
handler.action;
elseif (trigger == "WhenYouAreIncapacitated") then
handler.object = "self.manager.watcher";
handler.trigger = "PlayerIncapacitated";
handler.action =
"self = ...; " ..
handler.action;
elseif (trigger == "WhenYouAreRevived") then
handler.object = "self.manager.watcher";
handler.trigger = "PlayerRevived";
handler.action =
"self = ...; " ..
handler.action;
elseif (trigger == "WhenPetChanges") then
handler.object = "self.manager.player";
handler.trigger = "PetChanged";
handler.action =
"self = ...; " ..
handler.action;
elseif (trigger == "WhenMountChanges") then
handler.object = "self.manager.player";
handler.trigger = "MountChanged";
handler.action =
"self = ...; " ..
handler.action;
elseif (trigger == "WhenCombatBegins") then
handler.object = "self.manager.player";
handler.trigger = "InCombatChanged";
handler.action =
"self, object = ...; " ..
"if (object:IsInCombat()) then " ..
handler.action ..
"end";
elseif (trigger == "WhenCombatEnds") then
handler.object = "self.manager.player";
handler.trigger = "InCombatChanged";
handler.action =
"self, object = ...; " ..
"if (not object:IsInCombat()) then " ..
handler.action ..
"end";
elseif (trigger == "WhenMouseArrives") then
handler.object = "self";
handler.trigger = "MouseArrived";
handler.action =
"self = ...; " ..
handler.action;
elseif (trigger == "WhenMouseDeparts") then
handler.object = "self";
handler.trigger = "MouseDeparted";
handler.action =
"self = ...; " ..
handler.action;
elseif (string.find(trigger, "WhenEventOccurs:")) then
local eventName = string.sub(trigger, 17);
handler.object = "self.manager:GetEventCallbacks()";
handler.trigger = eventName;
handler.action =
"self = ...; " ..
handler.action;
description.trigger = L:GetText("Triggers/WhenEventOccurs") .. ": " .. eventName;
elseif (trigger == "WhenTraitTreeChanges") then
handler.object = "self.manager.watcher";
handler.trigger = "TraitTreeChanged";
handler.action =
"self = ...; " ..
handler.action;
elseif (trigger == "WhenStanceChanges") then
handler.object = "self.manager.watcher";
handler.trigger = "PlayerStanceChanged";
handler.action =
"self = ...; " ..
handler.action;
else
error("Unknown event handler trigger: " .. tostring(trigger), 2);
end
L:SetContext(prevContext);
-- Save new event handler and activate it
handler.description = description.action .. " " .. description.trigger;
table.insert(self.settings.eventHandlers, handler);
self:SetWantsEvents(true);
self:SaveSettings(false, true);
end
function Node:RemoveEventHandler(h)
self:SetWantsEvents(false);
table.remove(self.settings.eventHandlers, h);
self:SetWantsEvents(true);
self:SaveSettings(false, true);
end
function Node:SetEventHandlersEnabled(enable)
self.settings.eventsEnabled = enable;
self:SetWantsEvents(enable);
self:SaveSettings(false, true);
end
function Node:StripSettingsForExport(settings)
settings.deletedBarIDs = nil;
settings.deletedGroupIDs = nil;
end
function Node:Export()
if (self.exportWindow) then
self.exportWindow:Close();
self.exportWindow = nil;
end
-- Compile the data to be exported
Puts(L:GetText("/ExportWindow/Exporting"));
local exportObjects = { [self.objectID] = {} };
self:SetWantsEvents(false); -- we don't want to save eventHandlers[].func values
DeepTableCopy(self.settings, exportObjects[self.objectID]);
self:SetWantsEvents(self.settings.eventsEnabled);
self:StripSettingsForExport(exportObjects[self.objectID]);
if (self:CanHaveChildren()) then
local descendentIDs = self:FindAllDescendentIDs(nil, true, true);
for d = 1, #descendentIDs do
local objectID = descendentIDs[d];
local object = self.manager.objects[objectID];
exportObjects[objectID] = {};
object:SetWantsEvents(false); -- we don't want to save eventHandlers[].func values
DeepTableCopy(object.settings, exportObjects[objectID]);
object:SetWantsEvents(object.settings.eventsEnabled);
self:StripSettingsForExport(exportObjects[objectID]);
end
end
-- Create the export window
local title = L:GetText("/ExportWindow/Title");
title = string.gsub(title, "<name>", self.settings.caption.text);
self.exportWindow = ExportWindow(title, exportObjects);
self.exportWindow.Closing = function()
self.exportWindow = nil;
end
end
function Node:ShowSettingsMenu(fromOptionsPanel, mouseX, mouseY, itemsToClick)
mouseX = mouseX or Turbine.UI.Display.GetMouseX();
mouseY = mouseY or Turbine.UI.Display.GetMouseY();
-- Build the settings menu.
self.settingsMenu = Turbine.UI.ContextMenu();
self.amSubMenuOf = nil;
self:AddSettingsMenuItem(self.settingsMenu, "Root", nil, fromOptionsPanel);
self.prevSettingsMenuArgs = { fromOptionsPanel or false, mouseX, mouseY };
self.settingsMenu:ShowMenuAt(mouseX, mouseY);
-- Click the desired items
local menuItem = self.settingsMenu;
while (itemsToClick and next(itemsToClick)) do
local itemName = table.remove(itemsToClick);
local item = menuItem._itemsByName[itemName];
if (item) then
item:GetParent():GetParent().FocusLost = nil;
DoCallbacks(item, "MouseEnter");
DoCallbacks(item, "MouseLeave");
menuItem = item;
end
end
end
function Node:RedisplayMenu(menuItem, otherItem)
local itemsClicked = {};
while (menuItem._name) do
table.insert(itemsClicked, menuItem._name);
menuItem = menuItem._parent;
end
if (otherItem) then
table.insert(itemsClicked, 1, otherItem);
end
-- Redisplay the settings menu and reselect all of the previously-selected menu items
local node = self.amSubMenuOf or self;
node.settingsMenu:Close();
table.insert(node.prevSettingsMenuArgs, itemsClicked);
DoAtNextFrame(function()
node:ShowSettingsMenu(unpack(node.prevSettingsMenuArgs));
end);
end
function Node:Destroy()
self:SetWantsEvents(false);
self:SetWantsUpdates(false);
if (self.settingsMenu) then
self.settingsMenu:Close();
end
if (self.captionEditor) then
self.captionEditor:Close();
end
if (self.exportWindow) then
self.exportWindow:Close();
end
if (self.importWindow) then
self.importWindow:Close();
end
if (self.colorPicker) then
self.colorPicker:Close();
end
self.manager.objects[self.objectID] = nil;
if (self.Log) then
DoCallbacks(self, "Log", {"destroyed", string.upper(self.settings.type)});
end
self:Close();
end