Minion Beta! - Help us test our new AddOn updater. Get it now!
Download
(56 Kb)
Download
Updated: 07-27-09 08:21 PM
Pictures
File Info
Updated:07-27-09 08:21 PM
Created:11-23-08 05:58 AM
Downloads:148,961
Favorites:178
MD5:
Portfolio  Popular! (More than 5000 hits)
Version: 1.23
by: AnduinLothar [More]
Interface Option Creation Utility
Library to register Blizzard Option Panels with an option table syntax.

Purpose
Portfolio was made to act as a bridge to accept a recognizable option table format (similar to Khaos and Ace) and convert it into a fully functional Blizzard Options Panel. Any Ace or Khaos registration should be fairly painless for an author to convert to use Portfolio, and new option sets should be easy to understand and construct without having to make any frames or manually manage controls.

LuaDocs
http://www.karlkfi.com/PortfolioDocs/
PortfolioDocs are also included in the download, but is not inside the addon folder itself to save space when embedding.

Feedback & Support
The best way you can help would be to try and write your own Portfolio config options and see if it behaves the way you'd expect. Report any bugs or confusing implementation using the Report Bugs button or Comments. I'm also always open to suggestions and code donations via the Feature Request link.
If you'd like to donate to show your support, that can be done through paypal with a paypal account or by credit card. Remember donations are much appreciated but non-contractual. Thank you!
Click here to lend your support!

Implemented Option Types
  • Header - CONTROLTYPE_HEADER
  • Text - CONTROLTYPE_TEXT
  • Checkbox - CONTROLTYPE_CHECKBOX
  • Slider - CONTROLTYPE_SLIDER
  • Button - CONTROLTYPE_BUTTON
  • DropDown - CONTROLTYPE_DROPDOWN
  • ColorPicker - CONTROLTYPE_COLORPICKER
  • EditBox - CONTROLTYPE_EDITBOX
  • Window - CONTROLTYPE_WINDOW

Option Attributes

Common Option Table Attribute Descriptions
  • id - Unique option id. Used to create the names of the option frames (No Spaces!). Key used to store the value in the saved variables table if cvar/uvar/tvar are nil.
  • type - Type Variable. ex: CONTROLTYPE_HEADER
  • text - Option text. String (with optional format string like %s or %.2f to insert value), function(control, key) returning a string, or both.
  • tooltipText - (Optional) Text used in hover tooltip. String, String with %s for value, or function(value) returning a String
  • init - (Optional) function(control) called after the option is created, for customization.
  • defaultValue - Default value for options
  • callback - (Optional) function(color, isGUI, isUpdate) called when the value is changed
    Note: isUpdate is true when control:Update() is called, when the callbacks are initialized after variables load.
  • cvar - (Optional) CVar, SetCVar(cvar, value)
  • event - (Optional) SetCVar argument, SetCVar(cvar, value, event), requires cvar
  • uvar - (Optional) Global Variable Name, setglobal(uvar, value)
  • tvar - (Optional) Table Variable Key, for optionsFrameRef.savedVarTable[self.tvar] = value or varTable[tvar] = value
  • varTable - (Optional) Custom Variable Table, requires tvar

Header
  • id
  • type - CONTROLTYPE_HEADER
  • text
  • subText - (Optional) Subheader Text
  • init

Text
  • id
  • type - CONTROLTYPE_TEXT
  • text
  • init

Checkbox
  • id
  • type - CONTROLTYPE_CHECKBOX
  • text - Text shown to the right of the checkbox
  • tooltipText
  • init
  • defaultValue - "0" or "1"
  • invert - (Optional) inverts the value of the checkbox, "1" means unchecked, "0" means checked
  • callback
  • dependentControls - (Optional) Table of frames to disable when this one is set to "0"
  • dependentOptions - (Optional) Table of id's of other options to disable when this one is set to "0"
  • cvar
  • event
  • uvar
  • tvar
  • varTable

Slider
  • id
  • type - CONTROLTYPE_SLIDER
  • text - Text shown above the slider
  • tooltipText
  • init
  • minText - (Optional) Text used under the left arrow
  • maxText - (Optional) Text used under the right arrow
  • minValue - Number (Used for minText if minText = nil)
  • maxValue - Number (Used for maxText if maxText = nil)
  • valueStep - Number, slider granularity, divides evenly into maxValue - minValue
  • defaultValue - Number, between minValue and maxValue
  • callback
  • cvar
  • event
  • uvar
  • tvar
  • varTable

Button
  • id
  • type - CONTROLTYPE_BUTTON
  • text - Text shown on the button
  • tooltipText
  • init
  • callback

Dropdown
  • id
  • type - CONTROLTYPE_DROPDOWN
  • text - (Optional) Text shown on the button
  • headerText - (Optional) Text shown above the button
  • tooltipText
  • defaultValue
  • menuList - List of buttons
  • width - (Optional) static width of the control
  • minWidth - (Optional) min width of the control, larger text will resize the contol. Default 100.
  • nochecks - (Optional) Boolean, don't initialize empty menuItem.checked
  • nofuncs - (Optional) Boolean, don't initialize empty menuItem.func
  • init
  • callback
  • cvar
  • event
  • uvar
  • tvar
  • varTable

ColorPicker
  • id
  • type - CONTROLTYPE_COLORPICKER
  • text - Text shown to the right of the color swatch
  • tooltipText
  • init
  • defaultValue - color table {r=#, g=#, b=#, opacity=#} (opacity is optional)
  • callback
  • hasOpacity - (Optional) boolean to show opacity slider
  • cancelFunc - (Optional) function to call when the color change is canceled, after it's reset to the previous color
  • cvar
  • event
  • uvar
  • tvar
  • varTable

EditBox
  • id
  • type - CONTROLTYPE_EDITBOX
  • headerText - (Optional) Text shown above the button
  • tooltipText
  • init
  • defaultValue
  • callback
  • cvar
  • event
  • uvar
  • tvar
  • varTable

Window
  • id
  • type - CONTROLTYPE_WINDOW
  • init
  • options - List of option tables
  • width - (Optional) Number, defaults to calculated based on parent width
  • height - (Optional) Number, defaults to 200

Notes on Dropdowns
This implementation of dropdowns is about half way between managed and unmanaged. It has some shortcuts, but is essentially blizzard's dropdown code at its core. Because of this it is very powerful and can be customized by advanced users to do almost anything. But for those of you new to dropdowns you don't have to be intimidated, because I've done all the setup for you. The minimum you have to supply is a table formatted list of buttons. Each button should have a text, and a value. The checks and callback will be managed if left empty.

For advanced users the func and checked attributes can be overriden. You can also use any of the normal dropdown attributes. See FrameXML/UIDropDownMenu.lua for a full list of menu item attributes. And as will all controls you can override any of the settings or methods using the init function if you need something more customized.

I've also simplified the dropdown button itself, using UIDropDownMenuTemplate as a template on top of which I've added shortcuts and modifications. Texture anchors have been modified to play nicely with control:SetWidth(x) so that you don't have to use UIDropDownMenu_SetWidth. The clickable/tooltip area has also been extended to cover the whole button.

Saved Variables
Portfolio uses LibDefaults to manage your defaults for you if you wish. The normal way to handle defaults is to put the name of your saved variable table in optionSetTable.savedVarTable, but you can also supply individual options with their own varTable. Then you can supply a tvar to be the index to that saved variable table, otherwise the id will be used as the index. Alternately you can supply an option with a cvar or uvar (global variable name) to use instead. Note that if you supply none of the above Portfolio simply won't handle your variables. You can then manually update the options using the callbacks and init functions. You can also supply optionSetTable.initCallbacks = false in order to disable callbacks being fired when after the variables load.

Since Portfolio has no saved variables of its own and allows you to be flexible with your saved variable structure you can easily use the same saved variables with or without Portfolio. Your Portfolio GUI options can be truly optional. I'd suggest using LibDefaults to save live memory and avoid saving/loading in default values, but you don't have to.

Registration
lua Code:
  1. -- Get a reference to the lib from LibStub
  2. -- If LibStub doesn't exist this will fail silently
  3. -- If LibStub exists but Portfolio does not this will print an error in chat and then fail
  4. -- Use LibStub("Portfolio", true) to fail silently if you want Portfolio options to be optional.
  5. local Portfolio = LibStub and LibStub("Portfolio")
  6. if not Portfolio then return end
  7. -- Create the option table for registration.
  8. local optionSetTable = {
  9.   -- option frame id, unique, no spaces
  10.   id = "PortfolioDemo";
  11.   text = "Header/Tab Title Text";
  12.   subText = "Sub header Text"
  13.   -- AddOn name for variable loading, if different from id
  14.   addon = "PortfolioDemo";
  15.   options = {
  16.     -- list of option tables goes here!
  17.     {
  18.       id = "option1";
  19.       -- option attributes go here
  20.     };
  21.     -- more option tables
  22.   };
  23.   -- (Optional) String or table of your addon's saved variables. Use SavedVariables in your toc!
  24.   savedVarTable = "PortfolioDemo_SavedVars";
  25. }
  26. local optionsFrame = Portfolio.RegisterOptionSet(optionSetTable)


Embedding
See PortfolioDocs for more information.

Examples
The PortfolioDemo addon is included in this package. It is disabled by default so it won't bother users, but it should be an invaluable resource to those of you who learn by example. It should have a variety of usages for each implemented option type.
v1.23
- Added static 'width' option for Dropwdown controls

v1.22
-Fixed a bug where disabling the about panel also disabled initial loading callbacks

v1.21
- Fixed text value insertion
- toc bump to 30100

v1.2
- Fixed bug with empty Windows
- Added more robust text value insertion, handling %.2f for example
- Added optionSetTable.about = false to opt out of the about panel
- Added ChangeLog.txt

v1.1
- Added CONTROLTYPE_WINDOW for child frame control windows (optionally scrollable)
- Modified Scrollbars to be inside the window, have a border, and still be scrollable while moused over
Window width is now modified depending on the visibility of the scrollbar.
- Renamed UpdateTextWrap to UpdateBox and it is now called on child controls when the window scroll box is changed
- Fixed an error with dropdown entry selection
- Modified SetRelativePoint for better extensibility:
Added xOffset and yOffset fields for modifying the default offset from the anchor control.
Added xOffsetRelative and yOffsetRelative fields for modifying the default offset of relatively anchored controls.
xOffset and xOffsetRelative are also used in calculating the default width for windows.

v1.0
- Added CONTROLTYPE_EDITBOX
- Removed isTemp and replaced it with isGUI which is only a passthrough value to the callback; text and saved var are still updated.
It is now: callback(value, isGUI, isUpdate)
isGUI is now passed as true for all GUI control interactions (but not for the Okay, Cancel and Default blizzard option panel buttons).
- Added control:Refresh() called when the blizzard options frame is shown
- Added control:Okay(), control:Cancel() and control:Reset() that are called for each control that has them when you click the blizzard interface buttons
- Fixed Cancel to correctly revert values/controls to their previous state. Doesn't pass isGUI.

v0.94
- Added CONTROLTYPE_COLORPICKER
- Added Portfolio.Round

v0.93
- Refactored some code/files
- Added PortfolioDocs (Using a custom LuaDoc format)
- Renamed checkbox.dependentOptions to dependentControlsByID for clarity

v0.92
- option:Enabled() now restores custom font object colors
- Fixed success and result global var leaks
- Added CONTROLTYPE_DROPDOWN
- Added control click sounds
- Fixed tooltipText to be optional

v0.91
- Fixed a bug with text functions

v0.9
- Added CONTROLTYPE_TEXT
- TODO: Fix Text height/wrapping
- Added control:Reset() - Disable() no longer resets.
- dependentOptions will reset after disabling, but dependentControls will not
- UpdateDependentControls renamed UpdateDependents, handles both dependentOptions and dependentControls
- slider:SetMinMaxValues(min, max) now updates the stored min/max and texts if minText/maxText are not set
- Enable/Disable now changes text color
- tooltipText is now as flexible as text
- Headers and Text controls now dynamically resize with text:UpdateTextWrap() called OnShow
- Refactored and abstracted much of the control functionality to Portfolio.Control and renamed files.
- Fixed a bunch of minor bugs

v0.8
- Text can now have %s or %d to be formatted with the option value. control:UpdateText() is called when an option is updated
- Added dependentControls and dependentOptions for CONTROLTYPE_CHECKBOX to Enable/Disable other options
- control:Disable() now resets the value to default
- Cleaned up OnShow code so it doesn't call callbacks excessively
- callback(value, isUpdate) now pass an extra boolean argument when called by control:Update() (used when loading vars)

v0.7
- Working Slider option

v0.6
- Now uses LibStub to handle library versioning
- Removed event handling code and default variable initialization in favor of using LibDefaults
- Upgraded to InterfaceOptionAboutPanel lib
- Removed noAutoDefault. Now always loads vars that have defaults set.
- loadVars is renamed initCallbacks and now defaults to true
- Changed how GetValue/SetValue/Update works on the options

v0.5
- Added control:init() function for custom modification to the config frame
- Added callbacks on vars loaded (or before init if LoD) if loadVars is set
- Added Button
- Added some Dropdown code (incomplete)
- Added AboutPanel generated from toc info

v0.4
- Refactored the code into 3 files
- Added some Slider code (incomplete)
- Changed the registration arguments to match blizzard's format

v0.3
- Only loads once if embedded
- Defaults are now defined on vars loaded (immediately if registered after) if a default is supplied and the saved variables are nil
- Added noAutoDefault param for options and option sets. If defined, option's value overrides set's values.

v0.2
- Added a scroll frame for the main option panel
- Slider in progress
- Code cleanup

v0.1
- Checkboxes work
Archived Files (12)
File Name
Version
Size
Author
Date
1.22
55kB
AnduinLothar
06-05-09 01:21 AM
1.21
55kB
AnduinLothar
04-16-09 07:10 PM
1.21
55kB
AnduinLothar
04-05-09 05:21 PM
1.2
55kB
AnduinLothar
03-23-09 03:02 AM
1.1
55kB
AnduinLothar
02-15-09 11:10 PM
1.0
47kB
AnduinLothar
12-20-08 03:53 PM
0.94
41kB
AnduinLothar
12-08-08 06:18 AM
0.93
38kB
AnduinLothar
12-03-08 11:43 PM
0.92
21kB
AnduinLothar
11-29-08 07:26 AM
0.91
19kB
AnduinLothar
11-28-08 06:05 PM
0.9
19kB
AnduinLothar
11-27-08 04:48 PM
0.8
17kB
AnduinLothar
11-23-08 05:58 AM


Post A Reply Comment Options
Unread 04-10-11, 05:38 AM  
sykopat
A Kobold Labourer

Forum posts: 1
File comments: 19
Uploads: 0
This error is thrown each time I log in, seem to be related to Portfolio:


Date: 2011-04-10 13:35:46
ID: 1
Error occured in: Global
Count: 8
Message: ..\FrameXML\RestrictedExecution.lua line 397:
Call failed: [string " local state = tonumber(newstate:match("(..."] line 1:
attempt to index local 'newstate' (a number value)
Debug:
[C]: ?
[C]: ?
..\FrameXML\RestrictedExecution.lua:397:
..\FrameXML\RestrictedExecution.lua:390
(tail call): ?
(tail call): ?
..\FrameXML\SecureHandlers.lua:113:
..\FrameXML\SecureHandlers.lua:108
[C]: SetAttribute()
..\FrameXML\SecureStateDriver.lua:114:
..\FrameXML\SecureStateDriver.lua:95
..\FrameXML\SecureStateDriver.lua:164:
..\FrameXML\SecureStateDriver.lua:146
[C]: SetAttribute()
..\FrameXML\SecureStateDriver.lua:11:
..\FrameXML\SecureStateDriver.lua:8
(tail call): ?
UnitFrameBuffs\PartyBuffs.lua:65: UpdatePartyMemberStateDriver()
UnitFrameBuffs\PartyBuffs.lua:170:
UnitFrameBuffs\PartyBuffs.lua:161
[C]: pcall()
Portfolio\Control.lua:133: SetValue()
Portfolio\Control\Checkbox.lua:78: SetValue()
Portfolio\Control.lua:154: Update()
Portfolio\Portfolio.lua:136: CallCallbacks()
Portfolio\Portfolio.lua:91: func()
...ce\AddOns\Portfolio\Libs\LibDefaults\LibDefaults.lua:158: InitAddOn()
...ce\AddOns\Portfolio\Libs\LibDefaults\LibDefaults.lua:328:
...ce\AddOns\Portfolio\Libs\LibDefaults\LibDefaults.lua:326
sykopat is offline Report comment to moderator  
Reply With Quote
Unread 12-14-10, 02:00 PM  
RaiGaL
A Kobold Labourer

Forum posts: 0
File comments: 21
Uploads: 0
Naitaeti what part should we replace with this?Thanks
RaiGaL is offline Report comment to moderator  
Reply With Quote
Unread 10-27-10, 04:17 PM  
Naitaeti
A Kobold Labourer
AddOn Author - Click to view AddOns

Forum posts: 0
File comments: 38
Uploads: 7
Bug with components in windows

Seems there's a bug that prevents controls in subwindows from being saved.

The following patch solves the problem:

Code:
diff --git a/EnergizeConfig/Libs/Portfolio/Control/Window.lua b/EnergizeConfig/Libs/Portfolio/Control/Window.lua                                                                             
index 3a3c81e..a4a2875 100644                                                                                                                                                                
--- a/EnergizeConfig/Libs/Portfolio/Control/Window.lua                                                                                                                                       
+++ b/EnergizeConfig/Libs/Portfolio/Control/Window.lua                                                                                                                                       
@@ -24,6 +24,8 @@ function Portfolio.Control.Window.Register(optionsFrame, option)
        --optionsFrame:SetPoint("TOPLEFT", parent, "TOPLEFT");                                                                                                                               
        --optionsFrame:SetPoint("BOTTOMRIGHT", parent, "BOTTOMRIGHT");                                                                                                                       
                                                                                                                                                                                             
+       control.savedVarTable = optionsFrame.savedVarTable                                                                                                                                   
+                                                                                                                                                                                            
        local scrollFrame = CreateFrame("ScrollFrame", controlName.."ScrollFrame", control, "UIPanelScrollFrameTemplate")                                                                    
        scrollFrame.scrollBarHideable = true
Naitaeti is offline Report comment to moderator  
Reply With Quote
Unread 10-15-10, 07:34 PM  
Cralor
Mmm... cookies!!!
 
Cralor's Avatar
AddOn Author - Click to view AddOns

Forum posts: 770
File comments: 321
Uploads: 7
Also note:

Always register your Portfolio Options AFTER your core Lua code.

This will save you some stress
__________________
Never be satisfied with satisfactory.
Cralor is offline Report comment to moderator  
Reply With Quote
Unread 07-11-10, 08:47 PM  
Cralor
Mmm... cookies!!!
 
Cralor's Avatar
AddOn Author - Click to view AddOns

Forum posts: 770
File comments: 321
Uploads: 7
Just for people's convenience, I have uploaded KarlKFI's PortfolioDocs to my web server: http://cralor.org/PortfolioDocs/

(His site is currently down.)

__________________
Never be satisfied with satisfactory.
Last edited by Cralor : 08-23-13 at 11:47 PM.
Cralor is offline Report comment to moderator  
Reply With Quote
Unread 02-24-10, 02:25 PM  
AnduinLothar
Nobody of Importance
 
AnduinLothar's Avatar
AddOn Author - Click to view AddOns

Forum posts: 95
File comments: 208
Uploads: 49
Re: Using Boolean for CheckBoxes...

Just use a callback wrapper:

callback = function(value, isGUI, isUpdate) yourcallback(value == "1", isGUI, isUpdate) end;

for converting in the opposite direction just use a ternary operator:

control:SetValue(yourvalue and "1" or "0")
Last edited by AnduinLothar : 02-24-10 at 02:33 PM.
AnduinLothar is offline Report comment to moderator  
Reply With Quote
Unread 02-20-10, 06:43 PM  
Zasurus
A Cyclonian
AddOn Author - Click to view AddOns

Forum posts: 42
File comments: 30
Uploads: 2
Using Boolean for CheckBoxes...

Hi, I am looking to convert from LibSimpleOptions to Portfolio but don't really want to rewite my whole addon to cope with all checkboxs returning 1 and 0 instead of a boolean. Is there a way to use boolean instead?

Thanks

Zas
Zasurus is offline Report comment to moderator  
Reply With Quote
Unread 02-18-09, 02:16 AM  
evl
A Kobold Labourer
 
evl's Avatar
AddOn Author - Click to view AddOns

Forum posts: 0
File comments: 65
Uploads: 8
Originally posted by AnduinLothar
[b]LibDefaults is not especially big (12KB), which includes LibStub (1.33KB), but that's a lot smaller than Portfolio (92KB). Note that these are file sizes, which only really directly effects load time with parsing and processing. As for processor and memory overhead I haven't run any extensive testing.
The amount of extra code required trying to get around Portfolio doesn't seem to be worth it, I think I just have to figure out how to get CurseForge to package Portfolio with my addons, sucks to have to download 900k worth of duplicate libraries though
evl is offline Report comment to moderator  
Reply With Quote
Unread 02-17-09, 04:14 PM  
AnduinLothar
Nobody of Importance
 
AnduinLothar's Avatar
AddOn Author - Click to view AddOns

Forum posts: 95
File comments: 208
Uploads: 49
LibDefaults is not especially big (12KB), which includes LibStub (1.33KB), but that's a lot smaller than Portfolio (92KB). Note that these are file sizes, which only really directly effects load time with parsing and processing. As for processor and memory overhead I haven't run any extensive testing.

You can just embed or require LibDefaults if you want Portfolio to be optional and still want the benefits of LibDefaults. You will still have to delay callbacks until the saved variables load, but you can utilize LibDefaults' SetScript for that so you dont have to make your own frame or event handler.

Something like:
lua Code:
  1. local optionTable = {
  2.   id = "evl_Test",
  3.   text = "Test",
  4.   savedVarTable = "evl_TestDB",
  5.   options = {
  6.     {
  7.       id = "OptionA",
  8.       text = "Option A",
  9.       type = CONTROLTYPE_CHECKBOX,
  10.       defaultValue = "1",
  11.       callback = function() print("Option A callback") end
  12.     },
  13.     {
  14.       id = "OptionB",
  15.       text = "Option B",
  16.       type = CONTROLTYPE_CHECKBOX,
  17.       defaultValue = "0"
  18.     },
  19.   }
  20. }
  21.  
  22. local Portfolio = LibStub("Portfolio", true)
  23. if Portfolio then
  24.   Portfolio.RegisterOptionSet(optionTable)
  25. else
  26.   local addonName = "MyAddonName"
  27.   local LibDefaults = LibStub("LibDefaults")
  28.  
  29.   --Init defaults
  30.   for _, option in ipairs(optionTable.options) do
  31.     if option.defaultValue ~= nil then
  32.       LibDefaults:SetDefault(addonName, option.id, option.defaultValue)
  33.     end
  34.   end
  35.  
  36.   --Init Callbacks
  37.   local CallCallbacks = function()
  38.     for _, option in ipairs(optionTable.options) do
  39.       if option.callback then
  40.         --args: value, isGUI, isUpdate
  41.         option.callback(evl_TestDB[option.id], false, true)
  42.       end
  43.     end
  44.   end
  45.   LibDefaults:SetScript(addonName, CallCallbacks)
  46. end

Note: that "evl_TestDB[option.id]" should be "evl_TestDB[option.id]" but the highlighting ate it!

That would mostly emulate what Portfolio does. Except it assumes that you want all your callbacks called. If you use buttons or some other plugin control type that has a callback but not a current value then you'd need to modify your CallCallbacks function to ignore those (something Portfolio does automatically).
Last edited by AnduinLothar : 02-17-09 at 05:10 PM.
AnduinLothar is offline Report comment to moderator  
Reply With Quote
Unread 02-17-09, 12:04 PM  
evl
A Kobold Labourer
 
evl's Avatar
AddOn Author - Click to view AddOns

Forum posts: 0
File comments: 65
Uploads: 8
Originally posted by AnduinLothar
That works, provided you make a frame and an event driver and run it on ADDON_LOADED. Otherwise your callbacks will always be fired based on the defaults and not on any changed saved variables.

Plus the way you have it written you're not passing the current values to the callbacks anyway, so that doesn't exactly mimic what Portfolio does, even if it works for your usage.

Also, some control callbacks are not meant to be called on init, like callbacks for buttons, which are only called when clicked.

Of course then if LibDefaults is not present you wont be able to reset to defaults and your saved variables will contain all unchanged defaults (which can increase loading time if there are a lot). But if you want to sacrifice that for the sake of addon size that's your call.
Aha so my implementation has some hitches

My point is, idealy I'd like people to be able to run all my addons without any libraries of any sort, but if they have said library they get a nice pretty GUI to play around with.

I'm not really sure how much overhead Portfolio adds other than static memory which isn't really a big deal I guess but it would be nice to know!

I have about 8-9 addons that are pretty small and I would hate to have to embed Portfolio in all of them.
Last edited by evl : 02-17-09 at 12:13 PM.
evl is offline Report comment to moderator  
Reply With Quote
Unread 02-17-09, 11:44 AM  
AnduinLothar
Nobody of Importance
 
AnduinLothar's Avatar
AddOn Author - Click to view AddOns

Forum posts: 95
File comments: 208
Uploads: 49
That works, provided you make a frame and an event driver and run it on ADDON_LOADED. Otherwise your callbacks will always be fired based on the defaults and not on any changed saved variables.

Plus the way you have it written you're not passing the current values to the callbacks anyway, so that doesn't exactly mimic what Portfolio does, even if it works for your usage.

Also, some control callbacks are not meant to be called on init, like callbacks for buttons, which are only called when clicked.

Of course then if LibDefaults is not present you wont be able to reset to defaults and your saved variables will contain all unchanged defaults (which can increase loading time if there are a lot). But if you want to sacrifice that for the sake of addon size that's your call.
Last edited by AnduinLothar : 02-17-09 at 11:54 AM.
AnduinLothar is offline Report comment to moderator  
Reply With Quote
Unread 02-17-09, 06:36 AM  
evl
A Kobold Labourer
 
evl's Avatar
AddOn Author - Click to view AddOns

Forum posts: 0
File comments: 65
Uploads: 8
I've gotten a bit further in my research towards a completely optional approach. My addons are known for their minimal size and I'd like to keep it that way.

I modified the way the initialization of the configuration is done and so far it's working out great.

Code:
local optionTable = {
  id = "evl_Test",
  text = "Test",
  savedVarTable = "evl_TestDB",
  options = {
    {
      id = "OptionA",
      text = "Option A",
      type = CONTROLTYPE_CHECKBOX,
      defaultValue = "1",
      callback = function() print("Option A callback") end
    },
    {
      id = "OptionB",
      text = "Option B",
      type = CONTROLTYPE_CHECKBOX,
      defaultValue = "0"
    },
  }
}

-- Check if we have the configuration library
local Portfolio = LibStub and LibStub("Portfolio", true)
if Portfolio then
  Portfolio.RegisterOptionSet(optionTable)
else
  evl_TestDB = evl_TestDB and evl_TestDB or {}
  
  for _, option in ipairs(optionTable.options) do
    local id = option.id
    
    if not evl_TestDB[id] then
      evl_TestDB[id] = option.defaultValue
    end
    
    if option.callback then
      option.callback()
    end
  end
end
What this code does is basically:
  1. Check if LibStub and Portfolio are available (note the true parameter to LibStub which suppresses any error messages if it can't be fetched).
  2. If Portfolio is present, register the options table normally.
  3. Otherwise check if the SavedVariables table exists, if it doesn't create a new table.
  4. Work through each option in the options table setting non-existing defaults (so values that were already written by Portfolio before the library was disabled/deleted are preserved) and calling each options callback.
Last edited by evl : 02-17-09 at 06:37 AM.
evl is offline Report comment to moderator  
Reply With Quote
Unread 02-16-09, 02:04 AM  
Last Zolex
A Kobold Labourer
AddOn Author - Click to view AddOns

Forum posts: 0
File comments: 3
Uploads: 1
Thank you!

Oh wonderful!

Your lib seems to be what I have been waiting for!!!

I am struggeling with blizzard options for so long now. I have two addons, one is successfully writing the options to the saved variables, the other is not and I am not sure why. Therefore I have not published it yet, though it works fine for me. Both addons use the blizzard interface for customization and it is working fine so far, except making the values persistent.

I wanted to write my addon without any other 3rd party lib, but for your fine collection, I'll make an exception.

I'll come back and praise you again, when I actually have applied your lib to my addons )

Last Zolex
Last Zolex is offline Report comment to moderator  
Reply With Quote
Unread 02-15-09, 07:57 PM  
AnduinLothar
Nobody of Importance
 
AnduinLothar's Avatar
AddOn Author - Click to view AddOns

Forum posts: 95
File comments: 208
Uploads: 49
Originally posted by evl
I've been working on incorporating Portfolio into my small addons and I've run into some design problems.

Firstly I'm having problems using callbacks on other controls, an example I would like to see is a slider that when changed updates the value of a text control (I really think this should be defaut in slider as there is currently no way of knowing the sliders current value).

Secondly, the handling of defaults via LibDefaults is nice and all but it creates a tight-coupling between the addon and Portfolio since disabling Portfolio will cause the addon to stop working due to the LibDefaults dependancy, currently I've implemented normal defaults handling to get around this (MyAddonDB = MyAddonDB or defaults) but it's not very pretty.

Lastly, would it be possible for the about page to be optional? Currently I feel it's just bloat and adds an extra level to every panel.
It might be a good idea to have a separate text below the slider that shows its value, but the way I implemented it was generic to all options:
option:SetValue calls self:UpdateText which updates the option text to the value of Portfolio.Control.GetValueText(control, "text") which returns control.text unless the text value is a function or a format string.

So by setting the text = "Name (%s)" your slider text will include the value.


As for saved variables you have a number of options. Either make your addon depend on or embed Portfolio which includes LibDefaults. Or make your addon depend on or embed LibDefaults. Or you can optionally depend on both. If LibDefaults isn't available then you are obviously going to have to handle your own variables. It was done this way for flexibility. You can decided if you want to go to the extra effort to make Portfolio and/or LibDefaults optional.


As for the about page, yes I can make it optional. But I'm going to leave that decision until I revamp the paging to better handle sub-pages, which is on the todo list. In the mean time you can put useful info in your toc file that will get displayed there, like Version, Author, X-Category, X-Website, and X-Email
Last edited by AnduinLothar : 02-15-09 at 08:04 PM.
AnduinLothar is offline Report comment to moderator  
Reply With Quote
Unread 02-15-09, 05:05 PM  
evl
A Kobold Labourer
 
evl's Avatar
AddOn Author - Click to view AddOns

Forum posts: 0
File comments: 65
Uploads: 8
I've been working on incorporating Portfolio into my small addons and I've run into some design problems.

Firstly I'm having problems using callbacks on other controls, an example I would like to see is a slider that when changed updates the value of a text control (I really think this should be defaut in slider as there is currently no way of knowing the sliders current value).

Secondly, the handling of defaults via LibDefaults is nice and all but it creates a tight-coupling between the addon and Portfolio since disabling Portfolio will cause the addon to stop working due to the LibDefaults dependancy, currently I've implemented normal defaults handling to get around this (MyAddonDB = MyAddonDB or defaults) but it's not very pretty.

Lastly, would it be possible for the about page to be optional? Currently I feel it's just bloat and adds an extra level to every panel.
Last edited by evl : 02-15-09 at 05:07 PM.
evl is offline Report comment to moderator  
Reply With Quote
Post A Reply



Category Jump:

Support AddOn Development!

You have just downloaded by the author . If you like this AddOn why not consider supporting the author? This author has set up a donation account. Donations ensure that authors can continue to develop useful tools for everyone.