-- ================================ -- Extension of AddTool, adds macros and scripts to the list -- If you wish to have "abbreviations" (OpIconString) for macros/scripts, -- best add them at the end of the filenames - they will look exactly like -- those of tools -- -- -- Changes to the original code by blazej/daniel are only loosely marked since so much was changed -- -- Change history: -- ------------------- -- Jan 27, 2012 (v2) -- -) List can be sorted independent of case (used to be the same way "Add Tool" does it as of now - listing items starting with lower case -- characters at the bottom of the list) -- -) Caches and settings are seperated for "Add Tool", "Add Anything" and "Add Anything Compact". They don't overwrite each others lists -- any more -- -) Files are checked strictly by ending of filename (formerly, e.g. ".eyeonscript.bak" would be found and added to the list as well, -- now only e.g. ".eyeonscript") -- -- Modified by Andreas Opferkuch -- andreas dot opferkuch at gmx dot at -- http://www.variations-of-shadow.com -- Modified: Mar 06, 2011 -- =============================== -- AddTool by eyeon software -- Modified by blazej floch -- List restriction by daniel koch, 22-Oct-09 -- == CHANGE BEGIN == -- ======================= -- load configuration -- ======================= fCfg = io.open("addanything.cfg", "r") -- enable everything by default globals.displayTools = 1 globals.displayMacros = 1 globals.displayScripts = 1 globals.caselessSorting = 1 if fCfg then strCfg = fCfg:read("*a") if string.len(strCfg) == 4 then globals.displayTools = tonumber(string.sub(strCfg, 1, 1)) globals.displayMacros = tonumber(string.sub(strCfg, 2, 2)) globals.displayScripts = tonumber(string.sub(strCfg, 3, 3)) globals.caselessSorting = tonumber(string.sub(strCfg, 4, 4)) end fCfg:close() end -- ======================= -- scans input path recursively and adds all files of certain filetype to list -- filetype without "." in the beginning function parseDir(inPath, fileType) local tempItems = readdir(inPath .. "*.*") local cntItems = #tempItems if cntItems > 0 then for j = 1, cntItems do if tempItems[j].IsDir then parseDir(inPath .. tempItems[j].Name .. "\\", fileType) --print(inPath .. tempItems[j].Name .. "\\") elseif string.lower(string.sub(tempItems[j].Name, -#fileType)) == fileType then local currName = tempItems[j].Name table.insert(alltools, { REGI_ClassType = fileType, REGS_ID = inPath .. currName, REGS_Name = string.sub(currName, 1, #currName - #fileType - 1), REGS_OpIconString = "..." } ) end end end end function addMacros() pathStr = comp:GetCompPathMap()["Macros:"] pathStr = pathStr .. ";" .. fusion:GetGlobalPathMap()["Macros:"] paths = eyeon.split(pathStr, ";") table.sort(paths) cntPaths = #paths i = 1 -- remove duplicate paths while i < cntPaths do if paths[i] == paths[i + 1] then table.remove(paths, i + 1) i = i - 1 cntPaths = cntPaths - 1 end i = i + 1 end for i, currPath in paths do currPath = MapPath(currPath) parseDir(currPath, "setting") end end function addScripts() pathStr = comp:GetCompPathMap()["Scripts:"] pathStr = pathStr .. ";" .. fusion:GetGlobalPathMap()["Scripts:"] paths = eyeon.split(pathStr, ";") table.sort(paths) cntPaths = #paths local i = 1 -- remove duplicate paths while i < cntPaths do if paths[i] == paths[i + 1] then table.remove(paths, i + 1) i = i - 1 cntPaths = cntPaths - 1 end i = i + 1 end for i, currPath in paths do currPath = MapPath(currPath) parseDir(currPath, "eyeonscript") end end -- == CHANGE END == function initList() -- Cache tool names and IDs first time round, to avoid delays if globals.__addanything_data then alltools = globals.__addanything_data else alltools = {} if globals.displayTools == 1 then alltools = fu:GetRegSummary(CT_Tool) -- Fill in missing entries for i,v in ipairs(alltools) do -- If there is no Name use the OpIconString if available if not v.REGS_Name then if not v.REGS_OpIconString then v.REGS_Name = "???" else v.REGS_Name = v.REGS_OpIconString end end -- If there is no OpIconString use the first 4 letter of the Name if available if not v.REGS_OpIconString then if not v.REGS_Name then v.REGS_OpIconString = "???" else v.REGS_OpIconString = string.sub(v.REGS_Name, 0, 4) end end end end -- == CHANGE BEGIN == if globals.displayMacros == 1 then addMacros() end if globals.displayScripts == 1 then addScripts() end -- == CHANGE END == alltools.lasttool = 1 globals.__addanything_data = alltools end end initList() tools = alltools local otherfield = { REGS_Name = "REGS_OpIconString", REGS_OpIconString = "REGS_Name" } function UpdateList(list, data) if globals.caselessSorting == 1 then table.sort(data, function(a,b) return (string.lower(a.REGS_Name) < string.lower(b.REGS_Name)) end) else table.sort(data, function(a,b) return (a.REGS_Name < b.REGS_Name) end) end list[1] = nil -- clears the list for i,v in ipairs(data) do -- == MY CHANGE BEGIN == if v.REGI_ClassType == "eyeonscript" or v.REGI_ClassType == "setting" then list[tostring(i)] = v.REGS_Name else list[tostring(i)] = v.REGS_Name .. " (" .. v.REGS_OpIconString .. ")" end -- == MY CHANGE END == end end -- Define our UI local toolid = nil local toollist = iup.list{expand="HORIZONTAL", size="x200", dropdown="NO"} UpdateList(toollist, tools) local toolname = iup.text{"", expand="HORIZONTAL"} local ok = iup.button{title = "OK", size=50, expand="NO"} local cancel = iup.button{title = "Cancel", size=50, expand="NO"} -- == MY CHANGE BEGIN == local refresh = iup.button{title = "Refresh", size=50, expand="NO"} -- checkState - used to check global values about what to display in the list and -- return ON/OFF values for checkboxes function checkState(stateOf) if stateOf == 1 then return "ON" end return "OFF" end local checkTools = iup.toggle{title="Tools", value = checkState(globals.displayTools) } local checkMacros = iup.toggle{title="Macros", value = checkState(globals.displayMacros) } local checkScripts = iup.toggle{title="Scripts", value = checkState(globals.displayScripts) } local displayFrame = iup.frame { iup.hbox { checkTools, iup.fill{SIZE=30}, checkMacros, iup.fill{SIZE=30}, checkScripts }; title="Display" } local checkSort = iup.toggle{title="Caseless sorting", value = checkState(globals.caselessSorting) } -- == MY CHANGE END == local dlg = iup.dialog { title = "Add Anything", foreground = "YES", margin = "10x10", defaultenter = ok, defaultesc = cancel, border = "NO", minbox = "NO", maxbox = "NO", menubox = "NO", resize = "NO", iup.vbox { toollist, toolname, iup.fill{size=5}, iup.hbox { iup.fill{}, ok, iup.fill{SIZE=30}, refresh, iup.fill{SIZE=30}, cancel, iup.fill{} -- ok, iup.fill{SIZE=50}, cancel, }, iup.hbox { iup.fill{}, displayFrame, iup.fill{} }, iup.hbox { checkSort } }, } iup.SetAttribute(dlg, "NATIVEPARENT", touserdata(fu:GetMainWindow())) function moveselection(num) movetoselection(num + toollist.value) end function movetoselection(num) num = math.min(math.max(1, num), #tools) toollist.value = num v = toollist[num] toolname.value = tools[num].REGS_Name toolname.selection = "1:1000" end function restrictlist(fromlist, text) local tolist = {} local lowtext = string.lower(text) local listsize = 0 local i,v -- restrict list to only those containing our text for i,v in ipairs(fromlist) do local lowname = string.lower(v.REGS_Name) if string.find(lowname, lowtext) -- search the name or string.find(string.lower(v.REGS_OpIconString), lowtext) -- search the icon string or string.find(string.gsub(lowname, " ", ""), lowtext) then -- search the name with spaces removed listsize = listsize + 1 tolist[listsize] = v end end UpdateList(toollist, tolist) -- now select one if listsize > 0 then local len = string.len(text) local sel = 0 -- look for a match at the start of the name for i,v in ipairs(tolist) do if string.lower(string.sub(v.REGS_Name,1,len)) == lowtext then sel = i break end end if sel == 0 then -- look for a match at the start of the icon string for i,v in ipairs(tolist) do if string.lower(string.sub(v.REGS_OpIconString,1,len)) == lowtext then sel = i break end end end if sel == 0 then sel = 1 end toollist.value = tostring(sel) end return tolist end function toolname:action(key, text) if key == iup.K_BS or key == iup.K_DEL or key == iup.K_cDEL then if string.len(text) > 0 then tools = restrictlist(alltools, text) else tools = alltools UpdateList(toollist, tools) self.value = "" end elseif key == iup.K_UP then moveselection(-1) elseif key == iup.K_PGUP then moveselection(-10) elseif key == iup.K_cPGUP then movetoselection(1) elseif key == iup.K_cHOME then tools = alltools UpdateList(toollist, tools) movetoselection(1) elseif key == iup.K_DOWN then moveselection(1) elseif key == iup.K_PGDN then moveselection(10) elseif key == iup.K_cPGDN then movetoselection(#tools) elseif key == iup.K_cEND then tools = alltools UpdateList(toollist, tools) movetoselection(#tools) elseif key >= 32 and key < 127 then tools = restrictlist(alltools, text) -- could restrict from tools list elseif key == 127 then -- Ctrl+Backspace text = string.sub(text, self.caret+1, 1000) tools = restrictlist(alltools, text) self.value = text -- else --print(key) end return iup.DEFAULT end function toollist:action(text, item, sel) toolname.value = tools[item].REGS_Name toolname.selection = "1:1000" iup.SetFocus(toolname) return iup.DEFAULT end function toollist:dblclick_cb(pos, text) -- not called? ok:action() end function ok:action() local num = tonumber(toollist.value) -- == MY CHANGE BEGIN == if num == 0 then return iup.CLOSE end -- == MY CHANGE END == if num <= #tools then local id = tools[num].REGS_ID alltools.lasttool = id toolid = id; return iup.CLOSE end end function cancel:action() -- dump(alltools) return iup.CLOSE end -- == MY CHANGE BEGIN == function refresh:action() globals.__addanything_data = nil initList() toolname:action(iup.K_DEL, toolname.value) return iup.DEFAULT end function checkTools:action(state) if state == 1 then globals.displayTools = 1 else globals.displayTools = 0 end refresh:action() end function checkMacros:action(state) if state == 1 then globals.displayMacros = 1 else globals.displayMacros = 0 end refresh:action() end function checkScripts:action(state) if state == 1 then globals.displayScripts = 1 else globals.displayScripts = 0 end refresh:action() end function checkSort:action(state) if state == 1 then globals.caselessSorting = 1 else globals.caselessSorting = 0 end refresh:action() end -- == MY CHANGE END == -- start with last tool local id = alltools.lasttool for i,v in ipairs(tools) do if v.REGS_ID == id then toollist.value = i toolname.value = v.REGS_Name break end end dlg:show() toolname.selection = "1:1000" status,err = pcall(iup.MainLoop) -- == CHANGE BEGIN == -- ======================= -- save configuration -- ======================= fCfg = io.open("addanything.cfg", "w+") if fCfg then fCfg:write(globals.displayTools .. globals.displayMacros .. globals.displayScripts .. globals.caselessSorting) fCfg:close() end -- ======================= -- == CHANGE END == dlg:destroy() -- Do the AddTool() after the iup dialog has closed, otherwise some fighting -- over window focus happens, causing a deadlock within Windows if toolid ~= nil then -- == MY CHANGE BEGIN == if string.find(toolid, ".setting") then toolid = string.gsub(toolid, "\\", "\\\\") comp:Paste(eyeon.readfile(toolid)) elseif string.find(toolid, ".eyeonscript") then toolid = string.gsub(toolid, "\\", "\\\\") composition:RunScript(toolid) else local tool = comp:AddTool(toolid, -32768, -32768) end -- == MY CHANGE END == end globals.__addanything_data = alltools if not status then print(err) end