View Single Post
05-09-14, 08:17 PM   #5
Billtopia
A Flamescale Wyrmkin
AddOn Author - Click to view addons
Join Date: Apr 2009
Posts: 110
so this is what I came up with with an explanation and it even works



lua Code:
  1. local eframe = 0
  2. local oldpos = -1
  3. local oldLinePixels= -1
  4. me2:SetScript("OnUpdate", function(self, elapsed)
  5.     eframe = eframe + 1
  6.     if eframe < 2 then return end
  7.     eframe = 0
  8.    
  9.     local cursorPos = me.CodeFrameEBox:GetCursorPosition()
  10.     if oldpos ~= cursorPos then
  11.         local pos = cursorPos
  12.         local linewidth = me.CodeFrameEBox:GetWidth()
  13.         local CRs
  14.         local code = { string.split("\n\r",me.CodeFrameEBox:GetText()) }
  15.         local ccode = { string.split("\n\r",coloredGetText(me.CodeFrameEBox)) }
  16.         local linestring = ""
  17.         local line = false
  18.         local currentLinePixels = 0
  19.        
  20.         -- Line Numbers section
  21.         for x = 1, #code do
  22.             StrLen:SetText( code[x]:len() >0 and code[x] or "X")
  23.            
  24.             CRs = math.floor(StrLen:GetStringHeight() / 12)
  25.             linestring = linestring..x..":"..string.rep("\r", CRs)
  26.            
  27.             if not(line) and pos - ccode[x]:len() <= 0 then
  28.                 line = x
  29.             elseif not( line ) then
  30.                 currentLinePixels = currentLinePixels + (CRs * 12)
  31.                 pos = -1 + pos - (ccode[x] and ccode[x]:len() or 0)
  32.             end
  33.         end
  34.         linestring = string.gsub( linestring, ("%d:"):format(line), ("|cFF00FF00%d:|r"):format(line), 1)
  35.         me.LineNumbers:SetText(linestring.."\n\n\nEOF\r")
  36.         oldpos = cursorPos
  37.        
  38.         -- line / col section
  39.         if pos == 0 then
  40.             me.pos:SetText( ("line: %d  char: %d"):format(line, 0))
  41.         else
  42.             local tempString = ccode[line] and ccode[line]:sub(1,pos) or ""
  43.             tempString = tempString:gsub("|c%x%x%x%x%x%x%x%x", "")
  44.             tempString = tempString:gsub("|r", "")
  45.             me.pos:SetText( ("line: %d  char: %d"):format(line, tempString:len()))
  46.         end
  47.        
  48.         -- scroll frame adjust section
  49.         if oldLinePixels ~= currentLinePixels and not( IsMouseButtonDown("LeftButton") ) then
  50.             local displayPixels = me.EBoxOverlay:GetHeight() --
  51.             local displayTop = me.ScrollFrame:GetVerticalScroll()
  52.             local displayBottom = displayTop + displayPixels
  53.             local edge = 48
  54.        
  55.             if currentLinePixels > displayTop + edge and currentLinePixels < displayBottom - edge then
  56.                 -- within viewing window so do nothing
  57.             elseif currentLinePixels < displayTop + edge and displayTop > 1 and currentLinePixels < oldLinePixels then
  58.                 me.ScrollFrame:SetVerticalScroll( currentLinePixels - edge )
  59.             elseif currentLinePixels > displayBottom - edge then
  60.                 me.ScrollFrame:SetVerticalScroll( currentLinePixels - displayPixels + edge)
  61.             end
  62.             oldLinePixels = currentLinePixels
  63.         end
  64.     end
  65.    
  66. end)

the editbox has a fonstring running down the left side of it and they are both attached to the scroll frame.
no messing with history lines for the editbox or any scrollingmessageframe there is a frame overlaying the editbox's visible area with the backdrop set to it so that the backdrop doesn't go scrolling around the screen.

it is in an OnUpdate as the the editing windows just about fills the screen (80% each direction) and it shows no real drop in fps when editing the code. when the cursor position changes in the me.CodeFrameEBox it then pulls both the text formatted by FAIAP and the un-keyword colored text and splits it by lf/cr into a table.


it then does a loop sending the uncolored text to a fontstring set the same width as the editbox, grabs its height and divides by the font height. (I tried just doing it by length of the string but that could not properly predict wordwrap)


it then increments the line number string adding blank lines if the code wraps across lines


it then checks if the cursor position is in the current line by comparing to the colored text
if not it increments the pixel count by the height of the code if it is it sets the line


finished with the loop it changes the current line number on the side to green to distinguish it from the other lines
it sets the line number string


it then takes the position within the colored text sting left from the loop and if it is 0 it knows you are at the start of the string, if not it has to split the string at pos, strip the FAIAP code coloring then get the length of the left over string to figure the position of the cursor in the edit box


then to adjust the scrolling frame by the active line being editied I use the height of the overlay which is set where the "window" of the editbox on the scroll frame is. (there is no predetermined size... all points are relative by screen size)


and yes the mouse check is important as if you don't check for the mouse being down you end up doing all sorts of text selection in the editbox.


figuring out the math for the scroll frame was a bit of a pain but it all works now

Last edited by Billtopia : 05-09-14 at 08:23 PM. Reason: a little more info
  Reply With Quote