Skip to content

Commit

Permalink
General code cleanups, and added some error messages to fix #11
Browse files Browse the repository at this point in the history
If you tried to call :AddData() too early from another addon, there was no guarantee that DevTool was initialized enough to be ready for the incoming data. I moved a couple items earlier in the loading process to try to help this, and added some safety checks and error messaging to handle this cleaner than just erroring out.
  • Loading branch information
brittyazel committed Jan 28, 2024
1 parent 21f22d5 commit 4a7414b
Show file tree
Hide file tree
Showing 10 changed files with 810 additions and 760 deletions.
2 changes: 1 addition & 1 deletion .github/FUNDING.yml
Original file line number Diff line number Diff line change
@@ -1,3 +1,3 @@
# These are supported funding model platforms

github: [brittyazel]
github: [ brittyazel ]
12 changes: 11 additions & 1 deletion .github/ISSUE_TEMPLATE/bug_report.md
Original file line number Diff line number Diff line change
Expand Up @@ -6,28 +6,38 @@ labels: bug
assignees: brittyazel

---
*When reporting, please verify the issue with only **this** addon enabled and no others unless explicitly reporting an incompatibility between this addon. Likewise, please fill in the below information to the best of your ability — this information helps us a great deal.*

*When reporting, please verify the issue with only **this** addon enabled and no others unless explicitly reporting an
incompatibility between this addon. Likewise, please fill in the below information to the best of your ability — this
information helps us a great deal.*

## Issue description:

*A clear and concise description of what the issue is (i.e. what went wrong and what should have happened).*

## How to reproduce:

*E.g., Steps to reproduce the behavior...*

1. *Go to '....'*
2. *Click on '....'*
3. *Scroll down to '....'*
4. *See error*

## Technical info:

- **Addon Version:** *[e.g., 1.2.1]*
- **Client:** *[e.g., Retail, Classic, PTR, or Beta]*
- **Client Patch Version:** *[e.g., 10.1.0]*

## Additional context:

*Add any other context about the problem here.*

## Screenshots:

*If applicable, add screenshots to help explain your problem.*

## Lua error log:

*Attach the Lua error log here (please use code tags)*
7 changes: 6 additions & 1 deletion .github/ISSUE_TEMPLATE/feature_request.md
Original file line number Diff line number Diff line change
Expand Up @@ -8,13 +8,18 @@ assignees: brittyazel
---

## Is your feature request related to a problem? Please describe:

*A clear and concise description detailing the problem. E.g., "I'm always frustrated when [...]"*

## Describe the solution you'd like to see implemented:

*A clear and concise description of what solution or behavior you would like to see implemented.*

## Describe alternatives you've considered:
*A clear and concise description of any alternative solutions or features you've considered, such as supplementing a different mod that contains the feature in question.*

*A clear and concise description of any alternative solutions or features you've considered, such as supplementing a
different mod that contains the feature in question.*

## Additional context:

*Add any other context, screenshots, sketches, etc. about the feature request here. A picture is worth 1000 words.*
41 changes: 24 additions & 17 deletions DevTool.lua
Original file line number Diff line number Diff line change
Expand Up @@ -29,20 +29,19 @@ DevTool.colors["ok"] = CreateColorFromHexString("FF00FF00")
--------------------Start of Functions-----------------------------------
-------------------------------------------------------------------------

--- **OnInitialize**, which is called directly after the addon is fully loaded.
--- do init tasks here, like loading the Saved Variables
--- or setting up slash commands.
--- Called directly after the addon is fully loaded.
--- We do initialization tasks here, such as loading our saved variables or setting up slash commands.
function DevTool:OnInitialize()
-- This table holds the contents of the current view window. Declare this table early so it can be used in other functions.
self.list = {}

self.db = LibStub("AceDB-3.0"):New("DevToolDatabase", self.DatabaseDefaults)
end

--- **OnEnable** which gets called during the PLAYER_LOGIN event, when most of the data provided by the game is already present.
--- Do more initialization here, that really enables the use of your addon.
--- Register Events, Hook functions, Create Frames, Get information from
--- the game that wasn't available in OnInitialize
--- Called during the PLAYER_LOGIN event when most of the data provided by the game is already present.
--- We perform more startup tasks here, such as registering events, hooking functions, creating frames, or getting
--- information from the game that wasn't yet available during :OnInitialize()
function DevTool:OnEnable()
self.list = {}

self:CreateChatCommands()

self.MainWindow = CreateFrame("Frame", "DevToolFrame", UIParent, "DevToolMainFrame")
Expand Down Expand Up @@ -82,12 +81,10 @@ function DevTool:OnEnable()

end

--- **OnDisable**, which is only called when your addon is manually being disabled.
--- Unhook, Unregister Events, Hide frames that you created.
--- You would probably only use an OnDisable if you want to
--- build a "standby" mode, or be able to toggle modules on/off.
--- Called when our addon is manually being disabled during a running session.
--- We primarily use this to unhook scripts, unregister events, or hide frames that we created.
function DevTool:OnDisable()

-- Empty --
end

-------------------------------------------------
Expand All @@ -106,7 +103,7 @@ function DevTool:CreateChatCommands()
print(self.colors.lightblue:WrapTextInColorCode("/dev: ") .. "Show/Hide the DevTool interface")
print(self.colors.lightblue:WrapTextInColorCode("/dev help: ") .. "Display help information in the chat window")
print(self.colors.lightblue:WrapTextInColorCode("/dev <name> <parent (optional)>: ") .. "Add a table within _G or _G.parent to the list")
print(self.colors.lightblue:WrapTextInColorCode("/dev find <part_of_name> <parent (optional)>: ") .."Add tables containing this partial name within _G or _G.parent to the list")
print(self.colors.lightblue:WrapTextInColorCode("/dev find <part_of_name> <parent (optional)>: ") .. "Add tables containing this partial name within _G or _G.parent to the list")
print(self.colors.lightblue:WrapTextInColorCode("/dev startswith <part_of_name> <parent (optional)>: ") .. "Add tables beginning with this partial name within _G or _G.parent to the list")
print(self.colors.lightblue:WrapTextInColorCode("/dev eventadd <event> <unit (optional)>: ") .. "Add event or unit event to the list")
print(self.colors.lightblue:WrapTextInColorCode("/dev eventstart <event> <unit (optional)>: ") .. "Begin monitoring this event or unit event")
Expand Down Expand Up @@ -223,9 +220,20 @@ end
--- Default behavior is shallow copy
--- @param dataName <string or nil> - name tag to show in UI for you variable.
function DevTool:AddData(data, dataName)
-- If the data is nil, print an error and abort
if not data then
self:Print("Error: The data being added does not exist. Aborting.")
return
end

if not dataName then
dataName = tostring(data)
end

if not self.list then
print("Error: DevTool list is not fully initialized. Please try again later in the loading process. Aborting.")
end

table.insert(self.list, self:NewElement(data, tostring(dataName)))
self:UpdateMainTableUI()
end
Expand Down Expand Up @@ -441,7 +449,6 @@ function DevTool:UpdateMainTableUI()
self:AddScrollFrameButtons(self.MainWindow.scrollFrame, "DevToolEntryTemplate")
self:UpdateScrollFrameRowSize(self.MainWindow.scrollFrame)


local offset = HybridScrollFrame_GetOffset(self.MainWindow.scrollFrame)
local totalRowsCount = #self.list

Expand All @@ -450,7 +457,7 @@ function DevTool:UpdateMainTableUI()
local linePlusOffset = k + offset;
if linePlusOffset <= totalRowsCount and (k - 1) * self.MainWindow.scrollFrame.buttons[1]:GetHeight() <
self.MainWindow.scrollFrame:GetHeight() then
self:UIUpdateMainTableButton(button, self.list[offset+counter], linePlusOffset)
self:UIUpdateMainTableButton(button, self.list[offset + counter], linePlusOffset)
counter = counter + 1
button:Show();
else
Expand Down
34 changes: 17 additions & 17 deletions Libs/embeds.xml
Original file line number Diff line number Diff line change
Expand Up @@ -5,22 +5,22 @@

<Ui xmlns="http://www.blizzard.com/wow/ui/" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://www.blizzard.com/wow/ui/
https://raw.githubusercontent.com/Gethe/wow-ui-source/live/Interface/FrameXML/UI_shared.xsd">
<!--Be very careful about the order of these loads. LibStub must come first, followed by CallbackHandler and Ace Locale. Ace GUI bust come before AceDBOptions. -->
<!--Be very careful about the order of these loads. LibStub must come first, followed by CallbackHandler and Ace Locale. Ace GUI bust come before AceDBOptions. -->

<Script file="LibStub\LibStub.lua"/>
<Include file="CallbackHandler-1.0\CallbackHandler-1.0.xml"/>
<Include file="AceLocale-3.0\AceLocale-3.0.xml"/>
<Include file="AceGUI-3.0\AceGUI-3.0.xml"/>
<Include file="AceAddon-3.0\AceAddon-3.0.xml"/>
<Include file="AceBucket-3.0\AceBucket-3.0.xml"/>
<Include file="AceComm-3.0\AceComm-3.0.xml"/>
<Include file="AceConfig-3.0\AceConfig-3.0.xml"/>
<Include file="AceConsole-3.0\AceConsole-3.0.xml"/>
<Include file="AceDB-3.0\AceDB-3.0.xml"/>
<Include file="AceDBOptions-3.0\AceDBOptions-3.0.xml"/>
<Include file="AceEvent-3.0\AceEvent-3.0.xml"/>
<Include file="AceHook-3.0\AceHook-3.0.xml"/>
<Include file="AceSerializer-3.0\AceSerializer-3.0.xml"/>
<Include file="AceTab-3.0\AceTab-3.0.xml"/>
<Include file="AceTimer-3.0\AceTimer-3.0.xml"/>
<Script file="LibStub\LibStub.lua"/>
<Include file="CallbackHandler-1.0\CallbackHandler-1.0.xml"/>
<Include file="AceLocale-3.0\AceLocale-3.0.xml"/>
<Include file="AceGUI-3.0\AceGUI-3.0.xml"/>
<Include file="AceAddon-3.0\AceAddon-3.0.xml"/>
<Include file="AceBucket-3.0\AceBucket-3.0.xml"/>
<Include file="AceComm-3.0\AceComm-3.0.xml"/>
<Include file="AceConfig-3.0\AceConfig-3.0.xml"/>
<Include file="AceConsole-3.0\AceConsole-3.0.xml"/>
<Include file="AceDB-3.0\AceDB-3.0.xml"/>
<Include file="AceDBOptions-3.0\AceDBOptions-3.0.xml"/>
<Include file="AceEvent-3.0\AceEvent-3.0.xml"/>
<Include file="AceHook-3.0\AceHook-3.0.xml"/>
<Include file="AceSerializer-3.0\AceSerializer-3.0.xml"/>
<Include file="AceTab-3.0\AceTab-3.0.xml"/>
<Include file="AceTimer-3.0\AceTimer-3.0.xml"/>
</Ui>
2 changes: 1 addition & 1 deletion Modules/Events.lua
Original file line number Diff line number Diff line change
Expand Up @@ -127,7 +127,7 @@ function DevTool:SetMonitorEventScript()
local args = { ... }
local event = args[1]
local unit
if #args > 1 and type(args[2])=="string" and string.find(event, "UNIT") then
if #args > 1 and type(args[2]) == "string" and string.find(event, "UNIT") then
unit = args[2]
end

Expand Down
18 changes: 9 additions & 9 deletions OptionsFrame.lua
Original file line number Diff line number Diff line change
Expand Up @@ -28,45 +28,45 @@ function DevTool:CreateColorPickerFrame(parent)
local relativePoint = "TOPLEFT"
local xOffset = 5
local yOffset = -5

-- Color Pickers
for _, menuItem in pairs({ "table", "function", "string", "number", "default" }) do

local ColorPicker = AceGUI:Create("ColorPicker")
ColorPicker:SetLabel(menuItem)
ColorPicker:SetHasAlpha(true)

ColorPicker:SetColor(unpack(self.db.profile.colorVals[menuItem]))

ColorPicker.frame:SetParent(parent)
ColorPicker.frame:SetPoint(point, relativeTo, relativePoint, xOffset, yOffset)

ColorPicker.frame:SetWidth(100)
ColorPicker.frame:SetHeight(25)

ColorPicker:SetCallback("OnValueChanged", function(widget, event, r, g, b, a)
self.db.profile.colorVals[menuItem] = { r, g, b, a }
self.colors[menuItem]:SetRGBA(r, g, b, a)
self:UpdateMainTableUI()
end)

ColorPicker.frame:Show()

point = "LEFT"
relativeTo = ColorPicker.frame
relativePoint = "RIGHT"
yOffset = 0
xOffset = 5
end

-- Text Size Slider
local TextSizeSlider = AceGUI:Create("Slider")
TextSizeSlider:SetSliderValues(8, 24, 1)
TextSizeSlider:SetValue(self.db.profile.fontSize)

TextSizeSlider.frame:SetParent(parent)
TextSizeSlider.frame:SetPoint(point, relativeTo, relativePoint, 0, 5)

TextSizeSlider.frame:SetWidth(200)

TextSizeSlider:SetCallback("OnValueChanged", function(widget, event, size)
Expand Down
66 changes: 47 additions & 19 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,24 +1,31 @@
# DevTool

DevTool is a multipurpose tool to assist with World of Warcraft addon development.
The core functionality is similar to a debugger, and it is capable of visualizing and inspecting tables, events, and function calls at runtime.
The core functionality is similar to a debugger, and it is capable of visualizing and inspecting tables, events, and
function calls at runtime.

This addon can help new and veteran developers alike by providing a visual representation of their tables and structures.
Examining the WoW API or your addon's variables in a table-like, columnar interface is much easier than using print(), /dump, or other chat debugging methods.
This addon can help new and veteran developers alike by providing a visual representation of their tables and
structures.
Examining the WoW API or your addon's variables in a table-like, columnar interface is much easier than using print(),
/dump, or other chat debugging methods.

---

## How To Use
While DevTool is fully capable of being used solely from its graphical interface, it also provides a simple API for incorporation into your codebase directly.

While DevTool is fully capable of being used solely from its graphical interface, it also provides a simple API for
incorporation into your codebase directly.
Use of this API will result in adding elements directly into the DevTool interface for inspection.

### Using `AddData()`:

The main (and only) public function provided by DevTool is `AddData(data, <some string name>)`

- This function adds data to the list so that you can explore its values in interface list.
- The 1st parameter is the object you wish to inspect.
- **Note**, the default behavior is to _shallow_ copy.
- The 2nd parameter is the name string to show in interface to identify your object.
- **Note**, if no name is provided, we will auto-generate one for you.
- The 1st parameter is the object you wish to inspect.
- **Note**, the default behavior is to _shallow_ copy.
- The 2nd parameter is the name string to show in interface to identify your object.
- **Note**, if no name is provided, we will auto-generate one for you.

Let's suppose you have the following code in your addon...

Expand All @@ -31,6 +38,7 @@ DevTool:AddData(var, "My local var")
...this code will add `var` as a new row in the DevTool user interface with the label `"My local var"`.

### Example of a very common use case:

Here is a simple implementation that wraps `DevTool:AddData()` and checks for the `DEBUG` flag to be set:

```lua
Expand All @@ -41,57 +49,77 @@ function ExampleAddon:AddToInspector(data, strName)
end
```

Using the above code as an example, we can then apply our new function all over the addon codebase wherever inspection is needed:
Using the above code as an example, we can then apply our new function all over the addon codebase wherever inspection
is needed:

```lua
ExampleAddon:AddToInspector(ExampleObject, "ExampleObjectName")
```

### How to use the sidebar:

There are three tabs in sidebar, and the text field has different behaviors for each.

- History tab:
- This text field takes the fully qualified name of a table, relative to `_G`. Likewise, entering `<fully_qualified_name>` into the DevTool text field is the same as typing `/dev <name> <parent>` in the chat window.
- This text field takes the fully qualified name of a table, relative to `_G`. Likewise,
entering `<fully_qualified_name>` into the DevTool text field is the same as typing `/dev <name> <parent>` in the
chat window.
- Events tab:
- This text field can only use `<event>` or `<event> <unit>`. Likewise, the same can be done in the chat window by typing `/dev eventadd <event>` or `/dev eventadd <event> <unit>`, where `<event>` is a [Blizzard API event](https://wowpedia.fandom.com/wiki/Events) string and `<unit>` is the cooresponding unit string.
- This text field can only use `<event>` or `<event> <unit>`. Likewise, the same can be done in the chat window by
typing `/dev eventadd <event>` or `/dev eventadd <event> <unit>`, where `<event>` is
a [Blizzard API event](https://wowpedia.fandom.com/wiki/Events) string and `<unit>` is the cooresponding unit
string.
- Fn Call Log tab:
- You can enter `<function> <parent>` into the text field, and it will try to find `_G.<parent>.<function>`. Likewise, the same can be done in the chat window by typeing `/dev logfn <function> <parent>`

- You can enter `<function> <parent>` into the text field, and it will try to find `_G.<parent>.<function>`.
Likewise, the same can be done in the chat window by typeing `/dev logfn <function> <parent>`

### How to use function arguments:
You can specify coma separated arguments that will be passed to any function DevTool attempts to execute. The values can be in the form of a `string`, `number`, `nil`, `boolean`, and/or `table`.

You can specify coma separated arguments that will be passed to any function DevTool attempts to execute. The values can
be in the form of a `string`, `number`, `nil`, `boolean`, and/or `table`.

- **Note**, _to pass a value with type `table` you have to specify prefix `t=`_.

Example passing arguments to a function `SomeFunction`:

- FN Call Args: `t=MyObject, 12, a12` becomes `SomeFunction(_G.MyObject, 12, a12)`
- FN Call Args: `t=MyObject.Frame1.Frame2` becomes `SomeFunction(_G.MyObject.Frame1.Frame2)`

### Chat commands:

- `/dev` - toggles the main UI window
- `/dev help` - Lists help actions in the chat window
- `/dev <command>` - Will execute one of the commands listed in the help menu

### Other functionality:

- Clicking on a table name will expand and show its children.
- Clicking on a function name will try to execute the function. **WARNING: BE CAREFUL**.
- **Note**: This will make use of any function arguments set, as described above.
- **Note**: This will make use of any function arguments set, as described above.
- If a table has WoW API `GetObjectType()` then its type will be visible in the value column.
- DevTool can monitor WoW API events similar to that of `/etrace`, we also include a button to launch /etrace if you would rather use the built in tool instead.
- DevTool can monitor WoW API events similar to that of `/etrace`, we also include a button to launch /etrace if you
would rather use the built in tool instead.
- DevTool can log function calls, their input args, and return values.
- **Note**: Strings in the 'value' column have no line breaks
- **Note**: Strings in the 'value' column have no line breaks

---

## Want to contribute?

* [Report Bugs and Request Features](https://github.com/brittyazel/DevTool/issues)
* [Source Code](https://github.com/brittyazel/DevTool)

---

## Want to Donate?
Making add-ons is a lot of work! Your help goes a huge way to making my add-on work possible. If you would like to Donate, [GitHub Sponsors](https://github.com/sponsors/brittyazel) is the preferred method.

Making add-ons is a lot of work! Your help goes a huge way to making my add-on work possible. If you would like to
Donate, [GitHub Sponsors](https://github.com/sponsors/brittyazel) is the preferred method.

---

## Credits:
DevTool is a continuation of the amazing [*ViragDevTool*](https://github.com/varren/ViragDevTool) addon started by Varren/Virag for World of Warcraft: Battle for Azeroth and prior. All credit for the idea and the work done prior to 2021 should go to him, accordingly.

DevTool is a continuation of the amazing [*ViragDevTool*](https://github.com/varren/ViragDevTool) addon started by
Varren/Virag for World of Warcraft: Battle for Azeroth and prior. All credit for the idea and the work done prior to
2021 should go to him, accordingly.
Loading

0 comments on commit 4a7414b

Please sign in to comment.