aboutsummaryrefslogtreecommitdiff
path: root/Programs/Ink.bup/ink.lua
diff options
context:
space:
mode:
Diffstat (limited to 'Programs/Ink.bup/ink.lua')
-rw-r--r--Programs/Ink.bup/ink.lua3153
1 files changed, 3153 insertions, 0 deletions
diff --git a/Programs/Ink.bup/ink.lua b/Programs/Ink.bup/ink.lua
new file mode 100644
index 0000000..49f6119
--- /dev/null
+++ b/Programs/Ink.bup/ink.lua
@@ -0,0 +1,3153 @@
+tArgs = {...}
+
+if OneOS then
+ --running under OneOS
+ OneOS.ToolBarColour = colours.grey
+ OneOS.ToolBarTextColour = colours.white
+end
+
+local _w, _h = term.getSize()
+
+local round = function(num, idp)
+ local mult = 10^(idp or 0)
+ return math.floor(num * mult + 0.5) / mult
+end
+
+UIColours = {
+ Toolbar = colours.grey,
+ ToolbarText = colours.lightGrey,
+ ToolbarSelected = colours.lightBlue,
+ ControlText = colours.white,
+ ToolbarItemTitle = colours.black,
+ Background = colours.lightGrey,
+ MenuBackground = colours.white,
+ MenuText = colours.black,
+ MenuSeparatorText = colours.grey,
+ MenuDisabledText = colours.lightGrey,
+ Shadow = colours.grey,
+ TransparentBackgroundOne = colours.white,
+ TransparentBackgroundTwo = colours.lightGrey,
+ MenuBarActive = colours.white
+}
+
+local getNames = peripheral.getNames or function()
+ local tResults = {}
+ for n,sSide in ipairs( rs.getSides() ) do
+ if peripheral.isPresent( sSide ) then
+ table.insert( tResults, sSide )
+ local isWireless = false
+ if not pcall(function()isWireless = peripheral.call(sSide, 'isWireless') end) then
+ isWireless = true
+ end
+ if peripheral.getType( sSide ) == "modem" and not isWireless then
+ local tRemote = peripheral.call( sSide, "getNamesRemote" )
+ for n,sName in ipairs( tRemote ) do
+ table.insert( tResults, sName )
+ end
+ end
+ end
+ end
+ return tResults
+end
+
+Peripheral = {
+ GetPeripheral = function(_type)
+ for i, p in ipairs(Peripheral.GetPeripherals()) do
+ if p.Type == _type then
+ return p
+ end
+ end
+ end,
+
+ Call = function(type, ...)
+ local tArgs = {...}
+ local p = Peripheral.GetPeripheral(type)
+ peripheral.call(p.Side, unpack(tArgs))
+ end,
+
+ GetPeripherals = function(filterType)
+ local peripherals = {}
+ for i, side in ipairs(getNames()) do
+ local name = peripheral.getType(side):gsub("^%l", string.upper)
+ local code = string.upper(side:sub(1,1))
+ if side:find('_') then
+ code = side:sub(side:find('_')+1)
+ end
+
+ local dupe = false
+ for i, v in ipairs(peripherals) do
+ if v[1] == name .. ' ' .. code then
+ dupe = true
+ end
+ end
+
+ if not dupe then
+ local _type = peripheral.getType(side)
+ local isWireless = false
+ if _type == 'modem' then
+ if not pcall(function()isWireless = peripheral.call(sSide, 'isWireless') end) then
+ isWireless = true
+ end
+ if isWireless then
+ _type = 'wireless_modem'
+ name = 'W '..name
+ end
+ end
+ if not filterType or _type == filterType then
+ table.insert(peripherals, {Name = name:sub(1,8) .. ' '..code, Fullname = name .. ' ('..side:sub(1, 1):upper() .. side:sub(2, -1)..')', Side = side, Type = _type, Wireless = isWireless})
+ end
+ end
+ end
+ return peripherals
+ end,
+
+ PresentNamed = function(name)
+ return peripheral.isPresent(name)
+ end,
+
+ CallType = function(type, ...)
+ local tArgs = {...}
+ local p = GetPeripheral(type)
+ return peripheral.call(p.Side, unpack(tArgs))
+ end,
+
+ CallNamed = function(name, ...)
+ local tArgs = {...}
+ return peripheral.call(name, unpack(tArgs))
+ end
+}
+
+TextLine = {
+ Text = "",
+ Alignment = AlignmentLeft,
+
+ Initialise = function(self, text, alignment)
+ local new = {} -- the new instance
+ setmetatable( new, {__index = self} )
+ new.Text = text
+ new.Alignment = alignment or AlignmentLeft
+ return new
+ end
+}
+
+local StripColours = function(str)
+ return str:gsub('['..string.char(14)..'-'..string.char(29)..']','')
+end
+
+Printer = {
+ Name = nil,
+ PeripheralType = 'printer',
+
+ paperLevel = function(self)
+ return Peripheral.CallNamed(self.Name, 'getPaperLevel')
+ end,
+
+ newPage = function(self)
+ return Peripheral.CallNamed(self.Name, 'newPage')
+ end,
+
+ endPage = function(self)
+ return Peripheral.CallNamed(self.Name, 'endPage')
+ end,
+
+ pageWrite = function(self, text)
+ return Peripheral.CallNamed(self.Name, 'write', text)
+ end,
+
+ setPageTitle = function(self, title)
+ return Peripheral.CallNamed(self.Name, 'setPageTitle', title)
+ end,
+
+ inkLevel = function(self)
+ return Peripheral.CallNamed(self.Name, 'getInkLevel')
+ end,
+
+ getCursorPos = function(self)
+ return Peripheral.CallNamed(self.Name, 'getCursorPos')
+ end,
+
+ setCursorPos = function(self, x, y)
+ return Peripheral.CallNamed(self.Name, 'setCursorPos', x, y)
+ end,
+
+ pageSize = function(self)
+ return Peripheral.CallNamed(self.Name, 'getPageSize')
+ end,
+
+ Present = function()
+ if Peripheral.GetPeripheral(Printer.PeripheralType) == nil then
+ return false
+ else
+ return true
+ end
+ end,
+
+ PrintLines = function(self, lines, title, copies)
+ local pages = {}
+ local pageLines = {}
+ for i, line in ipairs(lines) do
+ table.insert(pageLines, TextLine:Initialise(StripColours(line)))
+ if i % 25 == 0 then
+ table.insert(pages, pageLines)
+ pageLines = {}
+ end
+ end
+ if #pageLines ~= 0 then
+ table.insert(pages, pageLines)
+ end
+ return self:PrintPages(pages, title, copies)
+ end,
+
+ PrintPages = function(self, pages, title, copies)
+ copies = copies or 1
+ for c = 1, copies do
+ for p, page in ipairs(pages) do
+ if self:paperLevel() < #pages * copies then
+ return 'Add more paper to the printer'
+ end
+ if self:inkLevel() < #pages * copies then
+ return 'Add more ink to the printer'
+ end
+ self:newPage()
+ for i, line in ipairs(page) do
+ self:setCursorPos(1, i)
+ self:pageWrite(StripColours(line.Text))
+ end
+ if title then
+ self:setPageTitle(title)
+ end
+ self:endPage()
+ end
+ end
+ end,
+
+ Initialise = function(self, name)
+ if Printer.Present() then --fix
+ local new = {} -- the new instance
+ setmetatable( new, {__index = self} )
+ if name and Peripheral.PresentNamed(name) then
+ new.Name = name
+ else
+ new.Name = Peripheral.GetPeripheral(Printer.PeripheralType).Side
+ end
+ return new
+ end
+ end
+}
+
+Clipboard = {
+ Content = nil,
+ Type = nil,
+ IsCut = false,
+
+ Empty = function()
+ Clipboard.Content = nil
+ Clipboard.Type = nil
+ Clipboard.IsCut = false
+ end,
+
+ isEmpty = function()
+ return Clipboard.Content == nil
+ end,
+
+ Copy = function(content, _type)
+ Clipboard.Content = content
+ Clipboard.Type = _type or 'generic'
+ Clipboard.IsCut = false
+ end,
+
+ Cut = function(content, _type)
+ Clipboard.Content = content
+ Clipboard.Type = _type or 'generic'
+ Clipboard.IsCut = true
+ end,
+
+ Paste = function()
+ local c, t = Clipboard.Content, Clipboard.Type
+ if Clipboard.IsCut then
+ Clipboard.Empty()
+ end
+ return c, t
+ end
+}
+
+if OneOS and OneOS.Clipboard then
+ Clipboard = OneOS.Clipboard
+end
+
+Drawing = {
+
+ Screen = {
+ Width = _w,
+ Height = _h
+ },
+
+ DrawCharacters = function (x, y, characters, textColour,bgColour)
+ Drawing.WriteStringToBuffer(x, y, characters, textColour, bgColour)
+ end,
+
+ DrawBlankArea = function (x, y, w, h, colour)
+ Drawing.DrawArea (x, y, w, h, " ", 1, colour)
+ end,
+
+ DrawArea = function (x, y, w, h, character, textColour, bgColour)
+ --width must be greater than 1, other wise we get a stack overflow
+ if w < 0 then
+ w = w * -1
+ elseif w == 0 then
+ w = 1
+ end
+
+ for ix = 1, w do
+ local currX = x + ix - 1
+ for iy = 1, h do
+ local currY = y + iy - 1
+ Drawing.WriteToBuffer(currX, currY, character, textColour, bgColour)
+ end
+ end
+ end,
+
+ DrawImage = function(_x,_y,tImage, w, h)
+ if tImage then
+ for y = 1, h do
+ if not tImage[y] then
+ break
+ end
+ for x = 1, w do
+ if not tImage[y][x] then
+ break
+ end
+ local bgColour = tImage[y][x]
+ local textColour = tImage.textcol[y][x] or colours.white
+ local char = tImage.text[y][x]
+ Drawing.WriteToBuffer(x+_x-1, y+_y-1, char, textColour, bgColour)
+ end
+ end
+ elseif w and h then
+ Drawing.DrawBlankArea(x, y, w, h, colours.green)
+ end
+ end,
+ --using .nft
+ LoadImage = function(path)
+ local image = {
+ text = {},
+ textcol = {}
+ }
+ local fs = fs
+ if OneOS then
+ fs = OneOS.FS
+ end
+ if fs.exists(path) then
+ local _open = io.open
+ if OneOS then
+ _open = OneOS.IO.open
+ end
+ local file = _open(path, "r")
+ local sLine = file:read()
+ local num = 1
+ while sLine do
+ table.insert(image, num, {})
+ table.insert(image.text, num, {})
+ table.insert(image.textcol, num, {})
+
+ --As we're no longer 1-1, we keep track of what index to write to
+ local writeIndex = 1
+ --Tells us if we've hit a 30 or 31 (BG and FG respectively)- next char specifies the curr colour
+ local bgNext, fgNext = false, false
+ --The current background and foreground colours
+ local currBG, currFG = nil,nil
+ for i=1,#sLine do
+ local nextChar = string.sub(sLine, i, i)
+ if nextChar:byte() == 30 then
+ bgNext = true
+ elseif nextChar:byte() == 31 then
+ fgNext = true
+ elseif bgNext then
+ currBG = Drawing.GetColour(nextChar)
+ bgNext = false
+ elseif fgNext then
+ currFG = Drawing.GetColour(nextChar)
+ fgNext = false
+ else
+ if nextChar ~= " " and currFG == nil then
+ currFG = colours.white
+ end
+ image[num][writeIndex] = currBG
+ image.textcol[num][writeIndex] = currFG
+ image.text[num][writeIndex] = nextChar
+ writeIndex = writeIndex + 1
+ end
+ end
+ num = num+1
+ sLine = file:read()
+ end
+ file:close()
+ end
+ return image
+ end,
+
+ DrawCharactersCenter = function(x, y, w, h, characters, textColour,bgColour)
+ w = w or Drawing.Screen.Width
+ h = h or Drawing.Screen.Height
+ x = x or 0
+ y = y or 0
+ x = math.ceil((w - #characters) / 2) + x
+ y = math.floor(h / 2) + y
+
+ Drawing.DrawCharacters(x, y, characters, textColour, bgColour)
+ end,
+
+ GetColour = function(hex)
+ if hex == ' ' then
+ return colours.transparent
+ end
+ local value = tonumber(hex, 16)
+ if not value then return nil end
+ value = math.pow(2,value)
+ return value
+ end,
+
+ Clear = function (_colour)
+ _colour = _colour or colours.black
+ Drawing.ClearBuffer()
+ Drawing.DrawBlankArea(1, 1, Drawing.Screen.Width, Drawing.Screen.Height, _colour)
+ end,
+
+ Buffer = {},
+ BackBuffer = {},
+
+ DrawBuffer = function()
+ for y,row in pairs(Drawing.Buffer) do
+ for x,pixel in pairs(row) do
+ local shouldDraw = true
+ local hasBackBuffer = true
+ if Drawing.BackBuffer[y] == nil or Drawing.BackBuffer[y][x] == nil or #Drawing.BackBuffer[y][x] ~= 3 then
+ hasBackBuffer = false
+ end
+ if hasBackBuffer and Drawing.BackBuffer[y][x][1] == Drawing.Buffer[y][x][1] and Drawing.BackBuffer[y][x][2] == Drawing.Buffer[y][x][2] and Drawing.BackBuffer[y][x][3] == Drawing.Buffer[y][x][3] then
+ shouldDraw = false
+ end
+ if shouldDraw then
+ term.setBackgroundColour(pixel[3])
+ term.setTextColour(pixel[2])
+ term.setCursorPos(x, y)
+ term.write(pixel[1])
+ end
+ end
+ end
+ Drawing.BackBuffer = Drawing.Buffer
+ Drawing.Buffer = {}
+ term.setCursorPos(1,1)
+ end,
+
+ ClearBuffer = function()
+ Drawing.Buffer = {}
+ end,
+
+ WriteStringToBuffer = function (x, y, characters, textColour,bgColour)
+ for i = 1, #characters do
+ local character = characters:sub(i,i)
+ Drawing.WriteToBuffer(x + i - 1, y, character, textColour, bgColour)
+ end
+ end,
+
+ WriteToBuffer = function(x, y, character, textColour,bgColour)
+ x = round(x)
+ y = round(y)
+ if bgColour == colours.transparent then
+ Drawing.Buffer[y] = Drawing.Buffer[y] or {}
+ Drawing.Buffer[y][x] = Drawing.Buffer[y][x] or {"", colours.white, colours.black}
+ Drawing.Buffer[y][x][1] = character
+ Drawing.Buffer[y][x][2] = textColour
+ else
+ Drawing.Buffer[y] = Drawing.Buffer[y] or {}
+ Drawing.Buffer[y][x] = {character, textColour, bgColour}
+ end
+ end,
+}
+
+Current = {
+ Document = nil,
+ TextInput = nil,
+ CursorPos = {1,1},
+ CursorColour = colours.black,
+ Selection = {8, 36},
+ Window = nil,
+ Modified = false,
+}
+
+local isQuitting = false
+
+function OrderSelection()
+ if Current.Selection then
+ if Current.Selection[1] <= Current.Selection[2] then
+ return Current.Selection
+ else
+ return {Current.Selection[2], Current.Selection[1]}
+ end
+ end
+end
+
+function StripColours(str)
+ return str:gsub('['..string.char(14)..'-'..string.char(29)..']','')
+end
+
+function FindColours(str)
+ local _, count = str:gsub('['..string.char(14)..'-'..string.char(29)..']','')
+ return count
+end
+
+ColourFromCharacter = function(character)
+ local n = character:byte() - 14
+ if n > 16 then
+ return nil
+ else
+ return 2^n
+ end
+end
+
+CharacterFromColour = function(colour)
+ return string.char(math.floor(math.log(colour)/math.log(2))+14)
+end
+
+Events = {}
+
+Button = {
+ X = 1,
+ Y = 1,
+ Width = 0,
+ Height = 0,
+ BackgroundColour = colours.lightGrey,
+ TextColour = colours.white,
+ ActiveBackgroundColour = colours.lightGrey,
+ Text = "",
+ Parent = nil,
+ _Click = nil,
+ Toggle = nil,
+
+ AbsolutePosition = function(self)
+ return self.Parent:AbsolutePosition()
+ end,
+
+ Draw = function(self)
+ local bg = self.BackgroundColour
+ local tc = self.TextColour
+ if type(bg) == 'function' then
+ bg = bg()
+ end
+
+ if self.Toggle then
+ tc = UIColours.MenuBarActive
+ bg = self.ActiveBackgroundColour
+ end
+
+ local pos = GetAbsolutePosition(self)
+ Drawing.DrawBlankArea(pos.X, pos.Y, self.Width, self.Height, bg)
+ Drawing.DrawCharactersCenter(pos.X, pos.Y, self.Width, self.Height, self.Text, tc, bg)
+ end,
+
+ Initialise = function(self, x, y, width, height, backgroundColour, parent, click, text, textColour, toggle, activeBackgroundColour)
+ local new = {} -- the new instance
+ setmetatable( new, {__index = self} )
+ height = height or 1
+ new.Width = width or #text + 2
+ new.Height = height
+ new.Y = y
+ new.X = x
+ new.Text = text or ""
+ new.BackgroundColour = backgroundColour or colours.lightGrey
+ new.TextColour = textColour or colours.white
+ new.ActiveBackgroundColour = activeBackgroundColour or colours.lightGrey
+ new.Parent = parent
+ new._Click = click
+ new.Toggle = toggle
+ return new
+ end,
+
+ Click = function(self, side, x, y)
+ if self._Click then
+ if self:_Click(side, x, y, not self.Toggle) ~= false and self.Toggle ~= nil then
+ self.Toggle = not self.Toggle
+ Draw()
+ end
+ return true
+ else
+ return false
+ end
+ end
+}
+
+TextBox = {
+ X = 1,
+ Y = 1,
+ Width = 0,
+ Height = 0,
+ BackgroundColour = colours.lightGrey,
+ TextColour = colours.black,
+ Parent = nil,
+ TextInput = nil,
+ Placeholder = '',
+
+ AbsolutePosition = function(self)
+ return self.Parent:AbsolutePosition()
+ end,
+
+ Draw = function(self)
+ local pos = GetAbsolutePosition(self)
+ Drawing.DrawBlankArea(pos.X, pos.Y, self.Width, self.Height, self.BackgroundColour)
+ local text = self.TextInput.Value
+ if #tostring(text) > (self.Width - 2) then
+ text = text:sub(#text-(self.Width - 3))
+ if Current.TextInput == self.TextInput then
+ Current.CursorPos = {pos.X + 1 + self.Width-2, pos.Y}
+ end
+ else
+ if Current.TextInput == self.TextInput then
+ Current.CursorPos = {pos.X + 1 + self.TextInput.CursorPos, pos.Y}
+ end
+ end
+
+ if #tostring(text) == 0 then
+ Drawing.DrawCharacters(pos.X + 1, pos.Y, self.Placeholder, colours.lightGrey, self.BackgroundColour)
+ else
+ Drawing.DrawCharacters(pos.X + 1, pos.Y, text, self.TextColour, self.BackgroundColour)
+ end
+
+ term.setCursorBlink(true)
+
+ Current.CursorColour = self.TextColour
+ end,
+
+ Initialise = function(self, x, y, width, height, parent, text, backgroundColour, textColour, done, numerical)
+ local new = {} -- the new instance
+ setmetatable( new, {__index = self} )
+ height = height or 1
+ new.Width = width or #text + 2
+ new.Height = height
+ new.Y = y
+ new.X = x
+ new.TextInput = TextInput:Initialise(text or '', function(key)
+ if done then
+ done(key)
+ end
+ Draw()
+ end, numerical)
+ new.BackgroundColour = backgroundColour or colours.lightGrey
+ new.TextColour = textColour or colours.black
+ new.Parent = parent
+ return new
+ end,
+
+ Click = function(self, side, x, y)
+ Current.Input = self.TextInput
+ self:Draw()
+ end
+}
+
+TextInput = {
+ Value = "",
+ Change = nil,
+ CursorPos = nil,
+ Numerical = false,
+ IsDocument = nil,
+
+ Initialise = function(self, value, change, numerical, isDocument)
+ local new = {} -- the new instance
+ setmetatable( new, {__index = self} )
+ new.Value = tostring(value)
+ new.Change = change
+ new.CursorPos = #tostring(value)
+ new.Numerical = numerical
+ new.IsDocument = isDocument or false
+ return new
+ end,
+
+ Insert = function(self, str)
+ if self.Numerical then
+ str = tostring(tonumber(str))
+ end
+
+ local selection = OrderSelection()
+
+ if self.IsDocument and selection then
+ self.Value = string.sub(self.Value, 1, selection[1]-1) .. str .. string.sub( self.Value, selection[2]+2)
+ self.CursorPos = selection[1]
+ Current.Selection = nil
+ else
+ local _, newLineAdjust = string.gsub(self.Value:sub(1, self.CursorPos), '\n','')
+
+ self.Value = string.sub(self.Value, 1, self.CursorPos + newLineAdjust) .. str .. string.sub( self.Value, self.CursorPos + 1 + newLineAdjust)
+ self.CursorPos = self.CursorPos + 1
+ end
+
+ self.Change(key)
+ end,
+
+ Extract = function(self, remove)
+ local selection = OrderSelection()
+ if self.IsDocument and selection then
+ local _, newLineAdjust = string.gsub(self.Value:sub(selection[1], selection[2]), '\n','')
+ local str = string.sub(self.Value, selection[1], selection[2]+1+newLineAdjust)
+ if remove then
+ self.Value = string.sub(self.Value, 1, selection[1]-1) .. string.sub( self.Value, selection[2]+2+newLineAdjust)
+ self.CursorPos = selection[1] - 1
+ Current.Selection = nil
+ end
+ return str
+ end
+ end,
+
+ Char = function(self, char)
+ if char == 'nil' then
+ return
+ end
+ self:Insert(char)
+ end,
+
+ Key = function(self, key)
+ if key == keys.enter then
+ if self.IsDocument then
+ self.Value = string.sub(self.Value, 1, self.CursorPos ) .. '\n' .. string.sub( self.Value, self.CursorPos + 1 )
+ self.CursorPos = self.CursorPos + 1
+ end
+ self.Change(key)
+ elseif key == keys.left then
+ -- Left
+ if self.CursorPos > 0 then
+ local colShift = FindColours(string.sub( self.Value, self.CursorPos, self.CursorPos))
+ self.CursorPos = self.CursorPos - 1 - colShift
+ self.Change(key)
+ end
+
+ elseif key == keys.right then
+ -- Right
+ if self.CursorPos < string.len(self.Value) then
+ local colShift = FindColours(string.sub( self.Value, self.CursorPos+1, self.CursorPos+1))
+ self.CursorPos = self.CursorPos + 1 + colShift
+ self.Change(key)
+ end
+
+ elseif key == keys.backspace then
+ -- Backspace
+ if self.IsDocument and Current.Selection then
+ self:Extract(true)
+ self.Change(key)
+ elseif self.CursorPos > 0 then
+ local colShift = FindColours(string.sub( self.Value, self.CursorPos, self.CursorPos))
+ local _, newLineAdjust = string.gsub(self.Value:sub(1, self.CursorPos), '\n','')
+
+ self.Value = string.sub( self.Value, 1, self.CursorPos - 1 - colShift + newLineAdjust) .. string.sub( self.Value, self.CursorPos + 1 - colShift + newLineAdjust)
+ self.CursorPos = self.CursorPos - 1 - colShift
+ self.Change(key)
+ end
+ elseif key == keys.home then
+ -- Home
+ self.CursorPos = 0
+ self.Change(key)
+ elseif key == keys.delete then
+ if self.IsDocument and Current.Selection then
+ self:Extract(true)
+ self.Change(key)
+ elseif self.CursorPos < string.len(self.Value) then
+ self.Value = string.sub( self.Value, 1, self.CursorPos ) .. string.sub( self.Value, self.CursorPos + 2 )
+ self.Change(key)
+ end
+ elseif key == keys["end"] then
+ -- End
+ self.CursorPos = string.len(self.Value)
+ self.Change(key)
+ elseif key == keys.up and self.IsDocument then
+ -- Up
+ if Current.Document.CursorPos then
+ local page = Current.Document.Pages[Current.Document.CursorPos.Page]
+ self.CursorPos = page:GetCursorPosFromPoint(Current.Document.CursorPos.Collum + page.MarginX, Current.Document.CursorPos.Line - page.MarginY - 1 + Current.Document.ScrollBar.Scroll, true)
+ self.Change(key)
+ end
+ elseif key == keys.down and self.IsDocument then
+ -- Down
+ if Current.Document.CursorPos then
+ local page = Current.Document.Pages[Current.Document.CursorPos.Page]
+ self.CursorPos = page:GetCursorPosFromPoint(Current.Document.CursorPos.Collum + page.MarginX, Current.Document.CursorPos.Line - page.MarginY + 1 + Current.Document.ScrollBar.Scroll, true)
+ self.Change(key)
+ end
+ end
+ end
+}
+
+Menu = {
+ X = 0,
+ Y = 0,
+ Width = 0,
+ Height = 0,
+ Owner = nil,
+ Items = {},
+ RemoveTop = false,
+
+ Draw = function(self)
+ Drawing.DrawBlankArea(self.X + 1, self.Y + 1, self.Width, self.Height, UIColours.Shadow)
+ if not self.RemoveTop then
+ Drawing.DrawBlankArea(self.X, self.Y, self.Width, self.Height, UIColours.MenuBackground)
+ for i, item in ipairs(self.Items) do
+ if item.Separator then
+ Drawing.DrawArea(self.X, self.Y + i, self.Width, 1, '-', colours.grey, UIColours.MenuBackground)
+ else
+ local textColour = item.Colour or UIColours.MenuText
+ if (item.Enabled and type(item.Enabled) == 'function' and item.Enabled() == false) or item.Enabled == false then
+ textColour = UIColours.MenuDisabledText
+ end
+ Drawing.DrawCharacters(self.X + 1, self.Y + i, item.Title, textColour, UIColours.MenuBackground)
+ end
+ end
+ else
+ Drawing.DrawBlankArea(self.X, self.Y, self.Width, self.Height, UIColours.MenuBackground)
+ for i, item in ipairs(self.Items) do
+ if item.Separator then
+ Drawing.DrawArea(self.X, self.Y + i - 1, self.Width, 1, '-', colours.grey, UIColours.MenuBackground)
+ else
+ local textColour = item.Colour or UIColours.MenuText
+ if (item.Enabled and type(item.Enabled) == 'function' and item.Enabled() == false) or item.Enabled == false then
+ textColour = UIColours.MenuDisabledText
+ end
+ Drawing.DrawCharacters(self.X + 1, self.Y + i - 1, item.Title, textColour, UIColours.MenuBackground)
+
+ Drawing.DrawCharacters(self.X - 1 + self.Width-#item.KeyName, self.Y + i - 1, item.KeyName, textColour, UIColours.MenuBackground)
+ end
+ end
+ end
+ end,
+
+ NameForKey = function(self, key)
+ if key == keys.leftCtrl then
+ return '^'
+ elseif key == keys.tab then
+ return 'Tab'
+ elseif key == keys.delete then
+ return 'Delete'
+ elseif key == keys.n then
+ return 'N'
+ elseif key == keys.a then
+ return 'A'
+ elseif key == keys.s then
+ return 'S'
+ elseif key == keys.o then
+ return 'O'
+ elseif key == keys.z then
+ return 'Z'
+ elseif key == keys.y then
+ return 'Y'
+ elseif key == keys.c then
+ return 'C'
+ elseif key == keys.x then
+ return 'X'
+ elseif key == keys.v then
+ return 'V'
+ elseif key == keys.r then
+ return 'R'
+ elseif key == keys.l then
+ return 'L'
+ elseif key == keys.t then
+ return 'T'
+ elseif key == keys.h then
+ return 'H'
+ elseif key == keys.e then
+ return 'E'
+ elseif key == keys.p then
+ return 'P'
+ elseif key == keys.f then
+ return 'F'
+ elseif key == keys.m then
+ return 'M'
+ elseif key == keys.q then
+ return 'Q'
+ else
+ return '?'
+ end
+ end,
+
+ Initialise = function(self, x, y, items, owner, removeTop)
+ local new = {} -- the new instance
+ setmetatable( new, {__index = self} )
+ if not owner then
+ return
+ end
+
+ local keyNames = {}
+
+ for i, v in ipairs(items) do
+ items[i].KeyName = ''
+ if v.Keys then
+ for _i, key in ipairs(v.Keys) do
+ items[i].KeyName = items[i].KeyName .. self:NameForKey(key)
+ end
+ end
+ if items[i].KeyName ~= '' then
+ table.insert(keyNames, items[i].KeyName)
+ end
+ end
+ local keysLength = LongestString(keyNames)
+ if keysLength > 0 then
+ keysLength = keysLength + 2
+ end
+
+ new.Width = LongestString(items, 'Title') + 2 + keysLength
+ if new.Width < 10 then
+ new.Width = 10
+ end
+ new.Height = #items + 2
+ new.RemoveTop = removeTop or false
+ if removeTop then
+ new.Height = new.Height - 1
+ end
+
+ if y < 1 then
+ y = 1
+ end
+ if x < 1 then
+ x = 1
+ end
+
+ if y + new.Height > Drawing.Screen.Height + 1 then
+ y = Drawing.Screen.Height - new.Height
+ end
+ if x + new.Width > Drawing.Screen.Width + 1 then
+ x = Drawing.Screen.Width - new.Width
+ end
+
+
+ new.Y = y
+ new.X = x
+ new.Items = items
+ new.Owner = owner
+ return new
+ end,
+
+ New = function(self, x, y, items, owner, removeTop)
+ if Current.Menu and Current.Menu.Owner == owner then
+ Current.Menu = nil
+ return
+ end
+
+ local new = self:Initialise(x, y, items, owner, removeTop)
+ Current.Menu = new
+ return new
+ end,
+
+ Click = function(self, side, x, y)
+ local i = y-1
+ if self.RemoveTop then
+ i = y
+ end
+ if i >= 1 and y < self.Height then
+ if not ((self.Items[i].Enabled and type(self.Items[i].Enabled) == 'function' and self.Items[i].Enabled() == false) or self.Items[i].Enabled == false) and self.Items[i].Click then
+ self.Items[i]:Click()
+ if Current.Menu.Owner and Current.Menu.Owner.Toggle then
+ Current.Menu.Owner.Toggle = false
+ end
+ Current.Menu = nil
+ self = nil
+ end
+ return true
+ end
+ end
+}
+
+MenuBar = {
+ X = 1,
+ Y = 1,
+ Width = Drawing.Screen.Width,
+ Height = 1,
+ MenuBarItems = {},
+
+ AbsolutePosition = function(self)
+ return {X = self.X, Y = self.Y}
+ end,
+
+ Draw = function(self)
+ --Drawing.DrawArea(self.X - 1, self.Y, 1, self.Height, "|", UIColours.ToolbarText, UIColours.Background)
+
+ Drawing.DrawBlankArea(self.X, self.Y, self.Width, self.Height, colours.grey)
+ for i, button in ipairs(self.MenuBarItems) do
+ button:Draw()
+ end
+ end,
+
+ Initialise = function(self, items)
+ local new = {} -- the new instance
+ setmetatable( new, {__index = self} )
+ new.X = 1
+ new.Y = 1
+ new.MenuBarItems = items
+ return new
+ end,
+
+ AddToolbarItem = function(self, item)
+ table.insert(self.ToolbarItems, item)
+ self:CalculateToolbarItemPositions()
+ end,
+
+ CalculateToolbarItemPositions = function(self)
+ local currY = 1
+ for i, toolbarItem in ipairs(self.ToolbarItems) do
+ toolbarItem.Y = currY
+ currY = currY + toolbarItem.Height
+ end
+ end,
+
+ Click = function(self, side, x, y)
+ for i, item in ipairs(self.MenuBarItems) do
+ if item.X <= x and item.X + item.Width > x then
+ if item:Click(item, side, x - item.X + 1, 1) then
+ return true
+ end
+ end
+ end
+ return false
+ end
+}
+
+TextFormatPlainText = 1
+TextFormatInkText = 2
+
+Document = {
+ X = 1,
+ Y = 1,
+ PageSize = {Width = 25, Height = 21},
+ TextInput = nil,
+ Pages = {},
+ Format = TextFormatPlainText,
+ Title = '',
+ Path = nil,
+ ScrollBar = nil,
+ Lines = {},
+ CursorPos = nil,
+
+ CalculateLineWrapping = function(self)
+ local limit = self.PageSize.Width
+ local text = self.TextInput.Value
+ local lines = {''}
+ local words = {}
+
+ for word, space in text:gmatch('(%S+)(%s*)') do
+ for i = 1, math.ceil(#word/limit) do
+ local _space = ''
+ if i == math.ceil(#word/limit) then
+ _space = space
+ end
+ table.insert(words, {word:sub(1+limit*(i-1), limit*i), _space})
+ end
+ end
+
+ for i, ws in ipairs(words) do
+ local word = ws[1]
+ local space = ws[2]
+ local temp = lines[#lines] .. word .. space:gsub('\n','')
+ if #temp > limit then
+ table.insert(lines, '')
+ end
+ if space:find('\n') then
+ lines[#lines] = lines[#lines] .. word
+
+ space = space:gsub('\n', function()
+ table.insert(lines, '')
+ return ''
+ end)
+ else
+ lines[#lines] = lines[#lines] .. word .. space
+ end
+ end
+ return lines
+ end,
+
+ CalculateCursorPos = function(self)
+ local passedCharacters = 0
+ Current.CursorPos = nil
+ for p, page in ipairs(self.Pages) do
+ page:Draw()
+ if not Current.CursorPos then
+ for i, line in ipairs(page.Lines) do
+ local relCursor = self.TextInput.CursorPos - FindColours(self.TextInput.Value:sub(1,self.TextInput.CursorPos))
+ if passedCharacters + #StripColours(line.Text:gsub('\n','')) >= relCursor then
+ Current.CursorPos = {self.X + page.MarginX + (relCursor - passedCharacters), page.Y + 1 + i}
+ self.CursorPos = {Page = p, Line = i, Collum = relCursor - passedCharacters - FindColours(self.TextInput.Value:sub(1,self.TextInput.CursorPos-1))}
+ break
+ end
+ passedCharacters = passedCharacters + #StripColours(line.Text:gsub('\n',''))
+ end
+ end
+ end
+ end,
+
+ Draw = function(self)
+ self:CalculatePages()
+ self:CalculateCursorPos()
+ self.ScrollBar:Draw()
+ end,
+
+ CalculatePages = function(self)
+ self.Pages = {}
+ local lines = self:CalculateLineWrapping()
+ self.Lines = lines
+ local pageLines = {}
+ local totalPageHeight = (3 + self.PageSize.Height + 2 * Page.MarginY)
+ for i, line in ipairs(lines) do
+ table.insert(pageLines, TextLine:Initialise(line))
+ if i % self.PageSize.Height == 0 then
+ table.insert(self.Pages, Page:Initialise(self, pageLines, 3 - self.ScrollBar.Scroll + totalPageHeight*(#self.Pages)))
+ pageLines = {}
+ end
+ end
+ if #pageLines ~= 0 then
+ table.insert(self.Pages, Page:Initialise(self, pageLines, 3 - self.ScrollBar.Scroll + totalPageHeight*(#self.Pages)))
+ end
+
+ self.ScrollBar.MaxScroll = totalPageHeight*(#self.Pages) - Drawing.Screen.Height + 1
+ end,
+
+ ScrollToCursor = function(self)
+ self:CalculateCursorPos()
+ if Current.CursorPos and
+ (Current.CursorPos[2] > Drawing.Screen.Height
+ or Current.CursorPos[2] < 2) then
+ self.ScrollBar:DoScroll(Current.CursorPos[2] - Drawing.Screen.Height)
+ end
+ end,
+
+ SetSelectionColour = function(self, colour)
+ local selection = OrderSelection()
+ local text = self.TextInput:Extract(true)
+ local colChar = CharacterFromColour(colour)
+ local precedingColour = ''
+ if FindColours(self.TextInput.Value:sub(self.TextInput.CursorPos+1, self.TextInput.CursorPos+1)) == 0 then
+ for i = 1, self.TextInput.CursorPos do
+ local c = self.TextInput.Value:sub(self.TextInput.CursorPos - i,self.TextInput.CursorPos - i)
+ if FindColours(c) == 1 then
+ precedingColour = c
+ break
+ end
+ end
+ if precedingColour == '' then
+ precedingColour = CharacterFromColour(colours.black)
+ end
+ end
+
+ self.TextInput:Insert(colChar..StripColours(text)..precedingColour)
+ --text = text:gsub('['..string.char(14)..'-'..string.char(29)..']','')
+ end,
+
+ Initialise = function(self, text, title, path)
+ local new = {} -- the new instance
+ setmetatable( new, {__index = self} )
+ new.Title = title or 'New Document'
+ new.Path = path
+ new.X = (Drawing.Screen.Width - (new.PageSize.Width + 2*(Page.MarginX)))/2
+ new.Y = 2
+ new.TextInput = TextInput:Initialise(text, function()
+ new:ScrollToCursor()
+ Current.Modified = true
+ Draw()
+ end, false, true)
+ new.ScrollBar = ScrollBar:Initialise(Drawing.Screen.Width, new.Y, Drawing.Screen.Height-1, 0, nil, nil, nil, function()end)
+ Current.TextInput = new.TextInput
+ Current.ScrollBar = new.ScrollBar
+ return new
+ end
+}
+
+ScrollBar = {
+ X = 1,
+ Y = 1,
+ Width = 1,
+ Height = 1,
+ BackgroundColour = colours.grey,
+ BarColour = colours.lightBlue,
+ Parent = nil,
+ Change = nil,
+ Scroll = 0,
+ MaxScroll = 0,
+ ClickPoint = nil,
+
+ AbsolutePosition = function(self)
+ return self.Parent:AbsolutePosition()
+ end,
+
+ Draw = function(self)
+ local pos = GetAbsolutePosition(self)
+ local barHeight = self.Height - self.MaxScroll
+ if barHeight < 3 then
+ barHeight = 3
+ end
+ local percentage = (self.Scroll/self.MaxScroll)
+
+ Drawing.DrawBlankArea(pos.X, pos.Y, self.Width, self.Height, self.BackgroundColour)
+ Drawing.DrawBlankArea(pos.X, pos.Y + round(self.Height*percentage - barHeight*percentage), self.Width, barHeight, self.BarColour)
+ end,
+
+ Initialise = function(self, x, y, height, maxScroll, backgroundColour, barColour, parent, change)
+ local new = {} -- the new instance
+ setmetatable( new, {__index = self} )
+ new.Width = 1
+ new.Height = height
+ new.Y = y
+ new.X = x
+ new.BackgroundColour = backgroundColour or colours.grey
+ new.BarColour = barColour or colours.lightBlue
+ new.Parent = parent
+ new.Change = change or function()end
+ new.MaxScroll = maxScroll
+ new.Scroll = 0
+ return new
+ end,
+
+ DoScroll = function(self, amount)
+ amount = round(amount)
+ if self.Scroll < 0 or self.Scroll > self.MaxScroll then
+ return false
+ end
+ self.Scroll = self.Scroll + amount
+ if self.Scroll < 0 then
+ self.Scroll = 0
+ elseif self.Scroll > self.MaxScroll then
+ self.Scroll = self.MaxScroll
+ end
+ self.Change()
+ return true
+ end,
+
+ Click = function(self, side, x, y, drag)
+ local percentage = (self.Scroll/self.MaxScroll)
+ local barHeight = (self.Height - self.MaxScroll)
+ if barHeight < 3 then
+ barHeight = 3
+ end
+ local relScroll = (self.MaxScroll*(y + barHeight*percentage)/self.Height)
+ if not drag then
+ self.ClickPoint = self.Scroll - relScroll + 1
+ end
+
+ if self.Scroll-1 ~= relScroll then
+ self:DoScroll(relScroll-self.Scroll-1 + self.ClickPoint)
+ end
+ return true
+ end
+}
+
+AlignmentLeft = 1
+AlignmentCentre = 2
+AlignmentRight = 3
+
+TextLine = {
+ Text = "",
+ Alignment = AlignmentLeft,
+
+ Initialise = function(self, text, alignment)
+ local new = {} -- the new instance
+ setmetatable( new, {__index = self} )
+ new.Text = text
+ new.Alignment = alignment or AlignmentLeft
+ return new
+ end
+}
+
+local clickPos = 1
+Page = {
+ X = 1,
+ Y = 1,
+ Width = 1,
+ Height = 1,
+ MarginX = 3,
+ MarginY = 2,
+ BackgroundColour = colours.white,
+ TextColour = colours.white,
+ ActiveBackgroundColour = colours.lightGrey,
+ Lines = {},
+ Parent = nil,
+
+ AbsolutePosition = function(self)
+ return self.Parent:AbsolutePosition()
+ end,
+
+ Draw = function(self)
+ local pos = GetAbsolutePosition(self)
+
+ if pos.Y > Drawing.Screen.Height or pos.Y + self.Height < 1 then
+ return
+ end
+
+ Drawing.DrawBlankArea(pos.X+self.Width,pos.Y -1 + 1, 1, self.Height, UIColours.Shadow)
+ Drawing.DrawBlankArea(pos.X+1, pos.Y -1 + self.Height, self.Width, 1, UIColours.Shadow)
+ Drawing.DrawBlankArea(pos.X, pos.Y -1, self.Width, self.Height, self.BackgroundColour)
+
+ local textColour = self.TextColour
+ if not Current.Selection then
+ for i, line in ipairs(self.Lines) do
+ local _c = 1
+ for c = 1, #line.Text do
+ local col = ColourFromCharacter(line.Text:sub(c,c))
+ if col then
+ textColour = col
+ else
+ Drawing.WriteToBuffer(pos.X + self.MarginX - 1 + _c, pos.Y -2 + i + self.MarginY, line.Text:sub(c,c), textColour, self.BackgroundColour)
+ _c = _c + 1
+ end
+ end
+ end
+ else
+ local selection = OrderSelection()
+ local char = 1
+ local textColour = self.TextColour
+ for i, line in ipairs(self.Lines) do
+ local _c = 1
+ for c = 1, #line.Text do
+ local col = ColourFromCharacter(line.Text:sub(c,c))
+ if col then
+ textColour = col
+ else
+ local tc = textColour
+ local colour = colours.white
+ if char >= selection[1] and char <= selection[2] then
+ colour = colours.lightBlue
+ tc = colours.white
+ end
+
+ Drawing.WriteToBuffer(pos.X + self.MarginX - 1 + _c, pos.Y -2 + i + self.MarginY, line.Text:sub(c,c), tc, colour)
+ _c = _c + 1
+ end
+ char = char + 1
+ end
+ end
+ end
+ end,
+
+ Initialise = function(self, parent, lines, y)
+ local new = {} -- the new instanc
+ setmetatable( new, {__index = self} )
+ new.Height = parent.PageSize.Height + 2 * self.MarginY
+ new.Width = parent.PageSize.Width + 2 * self.MarginX
+ new.X = 1
+ new.Y = y or 1
+ new.Lines = lines or {}
+ new.BackgroundColour = colours.white
+ new.TextColour = colours.black
+ new.Parent = parent
+ new.ClickPos = 1
+ return new
+ end,
+
+ GetCursorPosFromPoint = function(self, x, y, rel)
+ local pos = GetAbsolutePosition(self)
+ if rel then
+ pos = {Y = 0, X = 0}
+ end
+ local row = y - pos.Y + self.MarginY - self.Parent.ScrollBar.Scroll
+ local col = x - self.MarginX - pos.X + 1
+ local cursorPos = 0
+ if row <= 0 or col <= 0 then
+ return 0
+ end
+
+ if row > #self.Lines then
+ for i, v in ipairs(self.Lines) do
+ cursorPos = cursorPos + #v.Text-- - FindColours(v.Text)
+ end
+ return cursorPos
+ end
+
+ --term.setCursorPos(1,3)
+ local prevLineCount = 0
+ for i, v in ipairs(self.Lines) do
+ if i == row then
+ if col > #v.Text then
+ col = #v.Text-- + FindColours(v.Text)
+ else
+ col = col + FindColours(v.Text:sub(1, col))
+ end
+ --term.setCursorPos(1,2)
+ --print(prevLineCount)
+ cursorPos = cursorPos + col + 2 - i - prevLineCount
+ break
+ else
+ prevLineCount = FindColours(v.Text)
+ if prevLineCount ~= 0 then
+ prevLineCount = prevLineCount
+ end
+ cursorPos = cursorPos + #v.Text + 2 - i + FindColours(v.Text)
+ end
+ end
+
+ return cursorPos - 2
+ end,
+
+ Click = function(self, side, x, y, drag)
+ local cursorPos = self:GetCursorPosFromPoint(x, y)
+ self.Parent.TextInput.CursorPos = cursorPos
+ if drag == nil then
+ Current.Selection = nil
+ clickPos = x
+ else
+ local relCursor = cursorPos-- - FindColours(self.Parent.TextInput.Value:sub(1,cursorPos)) + 1
+ if not Current.Selection then
+ local adder = 1
+ if clickPos and clickPos < x then
+ adder = 0
+ end
+ Current.Selection = {relCursor + adder, relCursor + 1 + adder}
+ else
+ Current.Selection[2] = relCursor + 1
+ end
+ end
+ Draw()
+ return true
+ end
+}
+
+function GetAbsolutePosition(object)
+ local obj = object
+ local i = 0
+ local x = 1
+ local y = 1
+ while true do
+ x = x + obj.X - 1
+ y = y + obj.Y - 1
+
+ if not obj.Parent then
+ return {X = x, Y = y}
+ end
+
+ obj = obj.Parent
+
+ if i > 32 then
+ return {X = 1, Y = 1}
+ end
+
+ i = i + 1
+ end
+
+end
+
+function Draw()
+ if not Current.Window then
+ Drawing.Clear(colours.lightGrey)
+ else
+ Drawing.DrawArea(1, 2, Drawing.Screen.Width, Drawing.Screen.Height, '|', colours.black, colours.lightGrey)
+ end
+
+ if Current.Document then
+ Current.Document:Draw()
+ end
+
+ Current.MenuBar:Draw()
+
+ if Current.Window then
+ Current.Window:Draw()
+ end
+
+ if Current.Menu then
+ Current.Menu:Draw()
+ end
+
+ Drawing.DrawBuffer()
+
+ if Current.TextInput and Current.CursorPos and not Current.Menu and not(Current.Window and Current.Document and Current.TextInput == Current.Document.TextInput) and Current.CursorPos[2] > 1 then
+ term.setCursorPos(Current.CursorPos[1], Current.CursorPos[2])
+ term.setCursorBlink(true)
+ term.setTextColour(Current.CursorColour)
+ else
+ term.setCursorBlink(false)
+ end
+end
+MainDraw = Draw
+
+LongestString = function(input, key)
+ local length = 0
+ for i = 1, #input do
+ local value = input[i]
+ if key then
+ if value[key] then
+ value = value[key]
+ else
+ value = ''
+ end
+ end
+ local titleLength = string.len(value)
+ if titleLength > length then
+ length = titleLength
+ end
+ end
+ return length
+end
+
+function LoadMenuBar()
+ Current.MenuBar = MenuBar:Initialise({
+ Button:Initialise(1, 1, nil, nil, colours.grey, Current.MenuBar, function(self, side, x, y, toggle)
+ if toggle then
+ Menu:New(1, 2, {
+ {
+ Title = "New...",
+ Click = function()
+ Current.Document = Document:Initialise('')
+ end,
+ Keys = {
+ keys.leftCtrl,
+ keys.n
+ }
+ },
+ {
+ Title = 'Open...',
+ Click = function()
+ DisplayOpenDocumentWindow()
+ end,
+ Keys = {
+ keys.leftCtrl,
+ keys.o
+ }
+ },
+ {
+ Separator = true
+ },
+ {
+ Title = 'Save...',
+ Click = function()
+ SaveDocument()
+ end,
+ Keys = {
+ keys.leftCtrl,
+ keys.s
+ },
+ Enabled = function()
+ return true
+ end
+ },
+ {
+ Separator = true
+ },
+ {
+ Title = 'Print...',
+ Click = function()
+ PrintDocument()
+ end,
+ Keys = {
+ keys.leftCtrl,
+ keys.p
+ },
+ Enabled = function()
+ return true
+ end
+ },
+ {
+ Separator = true
+ },
+ {
+ Title = 'Quit',
+ Click = function()
+ Close()
+ end
+ },
+ --[[
+ {
+ Title = 'Save As...',
+ Click = function()
+
+ end
+ }
+ ]]--
+ }, self, true)
+ else
+ Current.Menu = nil
+ end
+ return true
+ end, 'File', colours.lightGrey, false),
+ Button:Initialise(7, 1, nil, nil, colours.grey, Current.MenuBar, function(self, side, x, y, toggle)
+ if not self.Toggle then
+ Menu:New(7, 2, {
+ --[[
+ {
+ Title = "Undo",
+ Click = function()
+ end,
+ Keys = {
+ keys.leftCtrl,
+ keys.z
+ },
+ Enabled = function()
+ return false
+ end
+ },
+ {
+ Title = 'Redo',
+ Click = function()
+
+ end,
+ Keys = {
+ keys.leftCtrl,
+ keys.y
+ },
+ Enabled = function()
+ return false
+ end
+ },
+ {
+ Separator = true
+ },
+ ]]--
+ {
+ Title = 'Cut',
+ Click = function()
+ Clipboard.Cut(Current.Document.TextInput:Extract(true), 'text')
+ end,
+ Keys = {
+ keys.leftCtrl,
+ keys.x
+ },
+ Enabled = function()
+ return Current.Document ~= nil and Current.Selection and Current.Selection[1] and Current.Selection[2] ~= nil
+ end
+ },
+ {
+ Title = 'Copy',
+ Click = function()
+ Clipboard.Copy(Current.Document.TextInput:Extract(), 'text')
+ end,
+ Keys = {
+ keys.leftCtrl,
+ keys.c
+ },
+ Enabled = function()
+ return Current.Document ~= nil and Current.Selection and Current.Selection[1] and Current.Selection[2] ~= nil
+ end
+ },
+ {
+ Title = 'Paste',
+ Click = function()
+ local paste = Clipboard.Paste()
+ Current.Document.TextInput:Insert(paste)
+ Current.Document.TextInput.CursorPos = Current.Document.TextInput.CursorPos + #paste - 1
+ end,
+ Keys = {
+ keys.leftCtrl,
+ keys.v
+ },
+ Enabled = function()
+ return Current.Document ~= nil and (not Clipboard.isEmpty()) and Clipboard.Type == 'text'
+ end
+ },
+ {
+ Separator = true,
+ },
+ {
+ Title = 'Select All',
+ Click = function()
+ Current.Selection = {1, #Current.Document.TextInput.Value:gsub('\n','')}
+ end,
+ Keys = {
+ keys.leftCtrl,
+ keys.a
+ },
+ Enabled = function()
+ return Current.Document ~= nil
+ end
+ }
+ }, self, true)
+ else
+ Current.Menu = nil
+ end
+ return true
+ end, 'Edit', colours.lightGrey, false)
+ })
+end
+
+function LoadMenuBar()
+ Current.MenuBar = MenuBar:Initialise({
+ Button:Initialise(1, 1, nil, nil, colours.grey, Current.MenuBar, function(self, side, x, y, toggle)
+ if toggle then
+ Menu:New(1, 2, {
+ {
+ Title = "New...",
+ Click = function()
+ Current.Document = Document:Initialise('')
+ end,
+ Keys = {
+ keys.leftCtrl,
+ keys.n
+ }
+ },
+ {
+ Title = 'Open...',
+ Click = function()
+ DisplayOpenDocumentWindow()
+ end,
+ Keys = {
+ keys.leftCtrl,
+ keys.o
+ }
+ },
+ {
+ Separator = true
+ },
+ {
+ Title = 'Save...',
+ Click = function()
+ SaveDocument()
+ end,
+ Keys = {
+ keys.leftCtrl,
+ keys.s
+ },
+ Enabled = function()
+ return Current.Document ~= nil
+ end
+ },
+ {
+ Separator = true
+ },
+ {
+ Title = 'Print...',
+ Click = function()
+ PrintDocument()
+ end,
+ Keys = {
+ keys.leftCtrl,
+ keys.p
+ },
+ Enabled = function()
+ return true
+ end
+ },
+ {
+ Separator = true
+ },
+ {
+ Title = 'Quit',
+ Click = function()
+ if Close() and OneOS then
+ OneOS.Close()
+ end
+ end,
+ Keys = {
+ keys.leftCtrl,
+ keys.q
+ }
+ },
+ --[[
+ {
+ Title = 'Save As...',
+ Click = function()
+
+ end
+ }
+ ]]--
+ }, self, true)
+ else
+ Current.Menu = nil
+ end
+ return true
+ end, 'File', colours.lightGrey, false),
+ Button:Initialise(7, 1, nil, nil, colours.grey, Current.MenuBar, function(self, side, x, y, toggle)
+ if not self.Toggle then
+ Menu:New(7, 2, {
+ --[[
+ {
+ Title = "Undo",
+ Click = function()
+ end,
+ Keys = {
+ keys.leftCtrl,
+ keys.z
+ },
+ Enabled = function()
+ return false
+ end
+ },
+ {
+ Title = 'Redo',
+ Click = function()
+
+ end,
+ Keys = {
+ keys.leftCtrl,
+ keys.y
+ },
+ Enabled = function()
+ return false
+ end
+ },
+ {
+ Separator = true
+ },
+ ]]--
+ {
+ Title = 'Cut',
+ Click = function()
+ Clipboard.Cut(Current.Document.TextInput:Extract(true), 'text')
+ end,
+ Keys = {
+ keys.leftCtrl,
+ keys.x
+ },
+ Enabled = function()
+ return Current.Document ~= nil and Current.Selection and Current.Selection[1] and Current.Selection[2] ~= nil
+ end
+ },
+ {
+ Title = 'Copy',
+ Click = function()
+ Clipboard.Copy(Current.Document.TextInput:Extract(), 'text')
+ end,
+ Keys = {
+ keys.leftCtrl,
+ keys.c
+ },
+ Enabled = function()
+ return Current.Document ~= nil and Current.Selection and Current.Selection[1] and Current.Selection[2] ~= nil
+ end
+ },
+ {
+ Title = 'Paste',
+ Click = function()
+ local paste = Clipboard.Paste()
+ Current.Document.TextInput:Insert(paste)
+ Current.Document.TextInput.CursorPos = Current.Document.TextInput.CursorPos + #paste - 1
+ end,
+ Keys = {
+ keys.leftCtrl,
+ keys.v
+ },
+ Enabled = function()
+ return Current.Document ~= nil and (not Clipboard.isEmpty()) and Clipboard.Type == 'text'
+ end
+ },
+ {
+ Separator = true,
+ },
+ {
+ Title = 'Select All',
+ Click = function()
+ Current.Selection = {1, #Current.Document.TextInput.Value:gsub('\n','')}
+ end,
+ Keys = {
+ keys.leftCtrl,
+ keys.a
+ },
+ Enabled = function()
+ return Current.Document ~= nil
+ end
+ }
+ }, self, true)
+ else
+ Current.Menu = nil
+ end
+ return true
+ end, 'Edit', colours.lightGrey, false),
+ Button:Initialise(13, 1, nil, nil, colours.grey, Current.MenuBar, function(self, side, x, y, toggle)
+ if not self.Toggle then
+ Menu:New(13, 2, {
+ {
+ Title = 'Red',
+ Click = function(item)
+ Current.Document:SetSelectionColour(item.Colour)
+ end,
+ Colour = colours.red,
+ Enabled = function()
+ return (Current.Document ~= nil and Current.Selection ~= nil and Current.Selection[1] ~= nil and Current.Selection[2] ~= nil)
+ end
+ },
+ {
+ Title = 'Orange',
+ Click = function(item)
+ Current.Document:SetSelectionColour(item.Colour)
+ end,
+ Colour = colours.orange,
+ Enabled = function()
+ return (Current.Document ~= nil and Current.Selection ~= nil and Current.Selection[1] ~= nil and Current.Selection[2] ~= nil)
+ end
+ },
+ {
+ Title = 'Yellow',
+ Click = function(item)
+ Current.Document:SetSelectionColour(item.Colour)
+ end,
+ Colour = colours.yellow,
+ Enabled = function()
+ return (Current.Document ~= nil and Current.Selection ~= nil and Current.Selection[1] ~= nil and Current.Selection[2] ~= nil)
+ end
+ },
+ {
+ Title = 'Pink',
+ Click = function(item)
+ Current.Document:SetSelectionColour(item.Colour)
+ end,
+ Colour = colours.pink,
+ Enabled = function()
+ return (Current.Document ~= nil and Current.Selection ~= nil and Current.Selection[1] ~= nil and Current.Selection[2] ~= nil)
+ end
+ },
+ {
+ Title = 'Magenta',
+ Click = function(item)
+ Current.Document:SetSelectionColour(item.Colour)
+ end,
+ Colour = colours.magenta,
+ Enabled = function()
+ return (Current.Document ~= nil and Current.Selection ~= nil and Current.Selection[1] ~= nil and Current.Selection[2] ~= nil)
+ end
+ },
+ {
+ Title = 'Purple',
+ Click = function(item)
+ Current.Document:SetSelectionColour(item.Colour)
+ end,
+ Colour = colours.purple,
+ Enabled = function()
+ return (Current.Document ~= nil and Current.Selection ~= nil and Current.Selection[1] ~= nil and Current.Selection[2] ~= nil)
+ end
+ },
+ {
+ Title = 'Light Blue',
+ Click = function(item)
+ Current.Document:SetSelectionColour(item.Colour)
+ end,
+ Colour = colours.lightBlue,
+ Enabled = function()
+ return (Current.Document ~= nil and Current.Selection ~= nil and Current.Selection[1] ~= nil and Current.Selection[2] ~= nil)
+ end
+ },
+ {
+ Title = 'Cyan',
+ Click = function(item)
+ Current.Document:SetSelectionColour(item.Colour)
+ end,
+ Colour = colours.cyan,
+ Enabled = function()
+ return (Current.Document ~= nil and Current.Selection ~= nil and Current.Selection[1] ~= nil and Current.Selection[2] ~= nil)
+ end
+ },
+ {
+ Title = 'Blue',
+ Click = function(item)
+ Current.Document:SetSelectionColour(item.Colour)
+ end,
+ Colour = colours.blue,
+ Enabled = function()
+ return (Current.Document ~= nil and Current.Selection ~= nil and Current.Selection[1] ~= nil and Current.Selection[2] ~= nil)
+ end
+ },
+ {
+ Title = 'Green',
+ Click = function(item)
+ Current.Document:SetSelectionColour(item.Colour)
+ end,
+ Colour = colours.green,
+ Enabled = function()
+ return (Current.Document ~= nil and Current.Selection ~= nil and Current.Selection[1] ~= nil and Current.Selection[2] ~= nil)
+ end
+ },
+ {
+ Title = 'Light Grey',
+ Click = function(item)
+ Current.Document:SetSelectionColour(item.Colour)
+ end,
+ Colour = colours.lightGrey,
+ Enabled = function()
+ return (Current.Document ~= nil and Current.Selection ~= nil and Current.Selection[1] ~= nil and Current.Selection[2] ~= nil)
+ end
+ },
+ {
+ Title = 'Grey',
+ Click = function(item)
+ Current.Document:SetSelectionColour(item.Colour)
+ end,
+ Colour = colours.grey,
+ Enabled = function()
+ return (Current.Document ~= nil and Current.Selection ~= nil and Current.Selection[1] ~= nil and Current.Selection[2] ~= nil)
+ end
+ },
+ {
+ Title = 'Black',
+ Click = function(item)
+ Current.Document:SetSelectionColour(item.Colour)
+ end,
+ Colour = colours.black,
+ Enabled = function()
+ return (Current.Document ~= nil and Current.Selection ~= nil and Current.Selection[1] ~= nil and Current.Selection[2] ~= nil)
+ end
+ },
+ {
+ Title = 'Brown',
+ Click = function(item)
+ Current.Document:SetSelectionColour(item.Colour)
+ end,
+ Colour = colours.brown,
+ Enabled = function()
+ return (Current.Document ~= nil and Current.Selection ~= nil and Current.Selection[1] ~= nil and Current.Selection[2] ~= nil)
+ end
+ }
+ }, self, true)
+ else
+ Current.Menu = nil
+ end
+ return true
+ end, 'Colour', colours.lightGrey, false)
+ })
+end
+
+function SplashScreen()
+ local w = colours.white
+ local b = colours.black
+ local u = colours.blue
+ local lb = colours.lightBlue
+ local splashIcon = {{w,w,w,b,w,w,w,b,w,w,w,},{w,w,w,b,w,w,w,b,w,w,w,},{w,w,w,b,u,u,u,b,w,w,w,},{w,b,b,u,u,u,u,u,b,b,w,},{b,u,u,lb,lb,u,u,u,u,u,b,},{b,u,lb,lb,u,u,u,u,u,u,b,},{b,u,lb,lb,u,u,u,u,u,u,b,},{b,u,u,u,u,u,u,u,u,u,b,},{w,b,b,b,b,b,b,b,b,b,w,},
+ ["text"]={{" "," "," "," "," "," "," "," "," "," "," ",},{" "," "," "," "," "," "," "," "," "," "," ",},{" "," "," "," "," "," "," "," "," "," "," ",},{" "," "," "," "," "," "," "," "," "," "," ",},{" "," "," "," "," "," "," "," "," "," "," ",},{" "," "," "," ","I","n","k"," "," "," "," ",},{" "," "," "," "," "," "," "," "," "," "," ",},{" "," ","b","y"," ","o","e","e","d"," "," "},{" "," "," "," "," "," "," "," "," "," "," ",},},
+ ["textcol"]={{w,w,w,w,w,w,w,w,w,w,w,},{w,w,w,w,w,w,w,w,w,w,w,},{w,w,w,w,w,w,w,w,w,w,w,},{w,w,w,w,w,w,w,w,w,w,w,},{w,w,w,w,w,w,w,w,w,w,w,},{w,w,w,w,w,w,w,w,w,w,w,},{w,w,w,w,w,w,w,w,w,w,w,},{lb,lb,lb,lb,lb,lb,lb,lb,lb,lb,lb,},{w,w,w,w,w,w,w,w,w,w,w,},},}
+ Drawing.Clear(colours.white)
+ Drawing.DrawImage((Drawing.Screen.Width - 11)/2, (Drawing.Screen.Height - 9)/2, splashIcon, 11, 9)
+ Drawing.DrawBuffer()
+ Drawing.Clear(colours.black)
+ parallel.waitForAny(function()sleep(1)end, function()os.pullEvent('mouse_click')end)
+end
+
+function Initialise(arg)
+ if OneOS then
+ fs = OneOS.FS
+ end
+
+ if not OneOS then
+ SplashScreen()
+ end
+ EventRegister('mouse_click', TryClick)
+ EventRegister('mouse_drag', function(event, side, x, y)TryClick(event, side, x, y, true)end)
+ EventRegister('mouse_scroll', Scroll)
+ EventRegister('key', HandleKey)
+ EventRegister('char', HandleKey)
+ EventRegister('timer', Timer)
+ EventRegister('terminate', function(event) if Close() then error( "Terminated", 0 ) end end)
+
+ LoadMenuBar()
+
+ --Current.Document = Document:Initialise('abcdefghijklmnopqrtuvwxy')--'Hello everybody!')
+ if tArgs[1] then
+ if fs.exists(tArgs[1]) then
+ OpenDocument(tArgs[1])
+ else
+ --new
+ end
+ else
+ Current.Document = Document:Initialise('')--'Hello everybody!')
+ end
+
+ --[[
+ if arg and fs.exists(arg) then
+ OpenDocument(arg)
+ else
+ DisplayNewDocumentWindow()
+ end
+ ]]--
+ Draw()
+
+ EventHandler()
+end
+
+local isControlPushed = false
+controlPushedTimer = nil
+closeWindowTimer = nil
+function Timer(event, timer)
+ if timer == closeWindowTimer then
+ if Current.Window then
+ Current.Window:Close()
+ end
+ Draw()
+ elseif timer == controlPushedTimer then
+ isControlPushed = false
+ end
+end
+
+local ignoreNextChar = false
+function HandleKey(...)
+ local args = {...}
+ local event = args[1]
+ local keychar = args[2]
+ --Mac left command character
+ if event == 'key' and keychar == keys.leftCtrl or keychar == keys.rightCtrl or keychar == 219 then
+ isControlPushed = true
+ controlPushedTimer = os.startTimer(0.5)
+ elseif isControlPushed then
+ if event == 'key' then
+ if CheckKeyboardShortcut(keychar) then
+ isControlPushed = false
+ ignoreNextChar = true
+ end
+ end
+ elseif ignoreNextChar then
+ ignoreNextChar = false
+ elseif Current.TextInput then
+ if event == 'char' then
+ Current.TextInput:Char(keychar)
+ elseif event == 'key' then
+ Current.TextInput:Key(keychar)
+ end
+ end
+end
+
+function CheckKeyboardShortcut(key)
+ local shortcuts = {}
+ shortcuts[keys.n] = function() Current.Document = Document:Initialise('') end
+ shortcuts[keys.o] = function() DisplayOpenDocumentWindow() end
+ shortcuts[keys.s] = function() if Current.Document ~= nil then SaveDocument() end end
+ shortcuts[keys.left] = function() if Current.TextInput then Current.TextInput:Key(keys.home) end end
+ shortcuts[keys.right] = function() if Current.TextInput then Current.TextInput:Key(keys["end"]) end end
+-- shortcuts[keys.q] = function() DisplayOpenDocumentWindow() end
+ if Current.Document ~= nil then
+ shortcuts[keys.s] = function() SaveDocument() end
+ shortcuts[keys.p] = function() PrintDocument() end
+ if Current.Selection and Current.Selection[1] and Current.Selection[2] ~= nil then
+ shortcuts[keys.x] = function() Clipboard.Cut(Current.Document.TextInput:Extract(true), 'text') end
+ shortcuts[keys.c] = function() Clipboard.Copy(Current.Document.TextInput:Extract(), 'text') end
+ end
+ if (not Clipboard.isEmpty()) and Clipboard.Type == 'text' then
+ shortcuts[keys.v] = function() local paste = Clipboard.Paste()
+ Current.Document.TextInput:Insert(paste)
+ Current.Document.TextInput.CursorPos = Current.Document.TextInput.CursorPos + #paste - 1
+ end
+ end
+ shortcuts[keys.a] = function() Current.Selection = {1, #Current.Document.TextInput.Value:gsub('\n','')} end
+ end
+
+ if shortcuts[key] then
+ shortcuts[key]()
+ Draw()
+ return true
+ else
+ return false
+ end
+end
+
+--[[
+ Check if the given object falls under the click coordinates
+]]--
+function CheckClick(object, x, y)
+ if object.X <= x and object.Y <= y and object.X + object.Width > x and object.Y + object.Height > y then
+ return true
+ end
+end
+
+--[[
+ Attempt to clicka given object
+]]--
+function DoClick(object, side, x, y, drag)
+ local obj = GetAbsolutePosition(object)
+ obj.Width = object.Width
+ obj.Height = object.Height
+ if object and CheckClick(obj, x, y) then
+ return object:Click(side, x - object.X + 1, y - object.Y + 1, drag)
+ end
+end
+
+--[[
+ Try to click at the given coordinates
+]]--
+function TryClick(event, side, x, y, drag)
+ if Current.Menu then
+ if DoClick(Current.Menu, side, x, y, drag) then
+ Draw()
+ return
+ else
+ if Current.Menu.Owner and Current.Menu.Owner.Toggle then
+ Current.Menu.Owner.Toggle = false
+ end
+ Current.Menu = nil
+ Draw()
+ return
+ end
+ elseif Current.Window then
+ if DoClick(Current.Window, side, x, y, drag) then
+ Draw()
+ return
+ else
+ Current.Window:Flash()
+ return
+ end
+ end
+ local interfaceElements = {}
+
+ table.insert(interfaceElements, Current.MenuBar)
+ table.insert(interfaceElements, Current.ScrollBar)
+ for i, page in ipairs(Current.Document.Pages) do
+ table.insert(interfaceElements, page)
+ end
+
+ for i, object in ipairs(interfaceElements) do
+ if DoClick(object, side, x, y, drag) then
+ Draw()
+ return
+ end
+ end
+ Draw()
+end
+
+function Scroll(event, direction, x, y)
+ if Current.Window and Current.Window.OpenButton then
+ Current.Document.Scroll = Current.Document.Scroll + direction
+ if Current.Window.Scroll < 0 then
+ Current.Window.Scroll = 0
+ elseif Current.Window.Scroll > Current.Window.MaxScroll then
+ Current.Window.Scroll = Current.Window.MaxScroll
+ end
+ Draw()
+ elseif Current.ScrollBar then
+ if Current.ScrollBar:DoScroll(direction*2) then
+ Draw()
+ end
+ end
+end
+
+
+--[[
+ Registers functions to run on certain events
+]]--
+function EventRegister(event, func)
+ if not Events[event] then
+ Events[event] = {}
+ end
+
+ table.insert(Events[event], func)
+end
+
+--[[
+ The main loop event handler, runs registered event functinos
+]]--
+function EventHandler()
+ while true do
+ local event, arg1, arg2, arg3, arg4 = os.pullEventRaw()
+ if Events[event] then
+ for i, e in ipairs(Events[event]) do
+ e(event, arg1, arg2, arg3, arg4)
+ end
+ end
+ end
+end
+
+
+local function Extension(path, addDot)
+ if not path then
+ return nil
+ elseif not string.find(fs.getName(path), '%.') then
+ if not addDot then
+ return fs.getName(path)
+ else
+ return ''
+ end
+ else
+ local _path = path
+ if path:sub(#path) == '/' then
+ _path = path:sub(1,#path-1)
+ end
+ local extension = _path:gmatch('%.[0-9a-z]+$')()
+ if extension then
+ extension = extension:sub(2)
+ else
+ --extension = nil
+ return ''
+ end
+ if addDot then
+ extension = '.'..extension
+ end
+ return extension:lower()
+ end
+end
+
+local RemoveExtension = function(path)
+ if path:sub(1,1) == '.' then
+ return path
+ end
+ local extension = Extension(path)
+ if extension == path then
+ return fs.getName(path)
+ end
+ return string.gsub(path, extension, ''):sub(1, -2)
+end
+
+local acknowledgedColour = false
+function PrintDocument()
+ if OneOS then
+ OneOS.LoadAPI('/System/API/Helpers.lua')
+ OneOS.LoadAPI('/System/API/Peripheral.lua')
+ OneOS.LoadAPI('/System/API/Printer.lua')
+ end
+
+ local doPrint = function()
+ local window = PrintDocumentWindow:Initialise():Show()
+ end
+
+ if Peripheral.GetPeripheral('printer') == nil then
+ ButtonDialougeWindow:Initialise('No Printer Found', 'Please place a printer next to your computer. Ensure you also insert dye (left slot) and paper (top slots)', 'Ok', nil, function(window, ok)
+ window:Close()
+ end):Show()
+ elseif not acknowledgedColour and FindColours(Current.Document.TextInput.Value) ~= 0 then
+ ButtonDialougeWindow:Initialise('Important', 'Due to the way printers work, you can\'t print in more than one colour. The dye you use will be the colour of the text.', 'Ok', nil, function(window, ok)
+ acknowledgedColour = true
+ window:Close()
+ doPrint()
+ end):Show()
+ else
+ doPrint()
+ end
+end
+
+function SaveDocument()
+ local function save()
+ local h = fs.open(Current.Document.Path, 'w')
+ if h then
+ if Current.Document.Format == TextFormatPlainText then
+ h.write(Current.Document.TextInput.Value)
+ else
+ local lines = {}
+ for p, page in ipairs(Current.Document.Pages) do
+ for i, line in ipairs(page.Lines) do
+ table.insert(lines, line)
+ end
+ end
+ h.write(textutils.serialize(lines))
+ end
+ Current.Modified = false
+ else
+ ButtonDialougeWindow:Initialise('Error', 'An error occured while saving the file, try again.', 'Ok', nil, function(window, ok)
+ window:Close()
+ end):Show()
+ end
+ h.close()
+ end
+
+ if not Current.Document.Path then
+ SaveDocumentWindow:Initialise(function(self, success, path)
+ self:Close()
+ if success then
+ local extension = ''
+ if Current.Document.Format == TextFormatPlainText then
+ extension = '.txt'
+ elseif Current.Document.Format == TextFormatInkText then
+ extension = '.ink'
+ end
+
+ if path:sub(-4) ~= extension then
+ path = path .. extension
+ end
+
+ Current.Document.Path = path
+ Current.Document.Title = fs.getName(path)
+ save()
+ end
+ if Current.Document then
+ Current.TextInput = Current.Document.TextInput
+ end
+ end):Show()
+ else
+ save()
+ end
+end
+
+function DisplayOpenDocumentWindow()
+ OpenDocumentWindow:Initialise(function(self, success, path)
+ self:Close()
+ if success then
+ OpenDocument(path)
+ end
+ end):Show()
+end
+
+function OpenDocument(path)
+ Current.Selection = nil
+ local h = fs.open(path, 'r')
+ if h then
+ Current.Document = Document:Initialise(h.readAll(), RemoveExtension(fs.getName(path)), path)
+ else
+ ButtonDialougeWindow:Initialise('Error', 'An error occured while opening the file, try again.', 'Ok', nil, function(window, ok)
+ window:Close()
+ if Current.Document then
+ Current.TextInput = Current.Document.TextInput
+ end
+ end):Show()
+ end
+ h.close()
+end
+
+local TidyPath = function(path)
+ path = '/'..path
+ local fs = fs
+ if OneOS then
+ fs = OneOS.FS
+ end
+ if fs.isDir(path) then
+ path = path .. '/'
+ end
+
+ path, n = path:gsub("//", "/")
+ while n > 0 do
+ path, n = path:gsub("//", "/")
+ end
+ return path
+end
+
+OpenDocumentWindow = {
+ X = 1,
+ Y = 1,
+ Width = 0,
+ Height = 0,
+ CursorPos = 1,
+ Visible = true,
+ Return = nil,
+ OpenButton = nil,
+ PathTextBox = nil,
+ CurrentDirectory = '/',
+ Scroll = 0,
+ MaxScroll = 0,
+ GoUpButton = nil,
+ SelectedFile = '',
+ Files = {},
+ Typed = false,
+
+ AbsolutePosition = function(self)
+ return {X = self.X, Y = self.Y}
+ end,
+
+ Draw = function(self)
+ if not self.Visible then
+ return
+ end
+ Drawing.DrawBlankArea(self.X + 1, self.Y+1, self.Width, self.Height, colours.grey)
+ Drawing.DrawBlankArea(self.X, self.Y, self.Width, 3, colours.lightGrey)
+ Drawing.DrawBlankArea(self.X, self.Y+1, self.Width, self.Height-6, colours.white)
+ Drawing.DrawCharactersCenter(self.X, self.Y, self.Width, 1, self.Title, colours.black, colours.lightGrey)
+ Drawing.DrawBlankArea(self.X, self.Y + self.Height - 5, self.Width, 5, colours.lightGrey)
+ self:DrawFiles()
+
+ if (fs.exists(self.PathTextBox.TextInput.Value)) or (self.SelectedFile and #self.SelectedFile > 0 and fs.exists(self.CurrentDirectory .. self.SelectedFile)) then
+ self.OpenButton.TextColour = colours.black
+ else
+ self.OpenButton.TextColour = colours.lightGrey
+ end
+
+ self.PathTextBox:Draw()
+ self.OpenButton:Draw()
+ self.CancelButton:Draw()
+ self.GoUpButton:Draw()
+ end,
+
+ DrawFiles = function(self)
+ for i, file in ipairs(self.Files) do
+ if i > self.Scroll and i - self.Scroll <= 11 then
+ if file == self.SelectedFile then
+ Drawing.DrawCharacters(self.X + 1, self.Y + i - self.Scroll, file, colours.white, colours.lightBlue)
+ elseif string.find(file, '%.txt') or string.find(file, '%.text') or string.find(file, '%.ink') or fs.isDir(self.CurrentDirectory .. file) then
+ Drawing.DrawCharacters(self.X + 1, self.Y + i - self.Scroll, file, colours.black, colours.white)
+ else
+ Drawing.DrawCharacters(self.X + 1, self.Y + i - self.Scroll, file, colours.grey, colours.white)
+ end
+ end
+ end
+ self.MaxScroll = #self.Files - 11
+ if self.MaxScroll < 0 then
+ self.MaxScroll = 0
+ end
+ end,
+
+ Initialise = function(self, returnFunc)
+ local new = {} -- the new instance
+ setmetatable( new, {__index = self} )
+ new.Width = 32
+ new.Height = 17
+ new.Return = returnFunc
+ new.X = math.ceil((Drawing.Screen.Width - new.Width) / 2)
+ new.Y = math.ceil((Drawing.Screen.Height - new.Height) / 2)
+ new.Title = 'Open Document'
+ new.Visible = true
+ new.CurrentDirectory = '/'
+ new.SelectedFile = nil
+ if OneOS and fs.exists('/Desktop/Documents/') then
+ new.CurrentDirectory = '/Desktop/Documents/'
+ end
+ new.OpenButton = Button:Initialise(new.Width - 6, new.Height - 1, nil, nil, colours.white, new, function(self, side, x, y, toggle)
+ if fs.exists(new.PathTextBox.TextInput.Value) and self.TextColour == colours.black and not fs.isDir(new.PathTextBox.TextInput.Value) then
+ returnFunc(new, true, TidyPath(new.PathTextBox.TextInput.Value))
+ elseif new.SelectedFile and self.TextColour == colours.black and fs.isDir(new.CurrentDirectory .. new.SelectedFile) then
+ new:GoToDirectory(new.CurrentDirectory .. new.SelectedFile)
+ elseif new.SelectedFile and self.TextColour == colours.black then
+ returnFunc(new, true, TidyPath(new.CurrentDirectory .. '/' .. new.SelectedFile))
+ end
+ end, 'Open', colours.black)
+ new.CancelButton = Button:Initialise(new.Width - 15, new.Height - 1, nil, nil, colours.white, new, function(self, side, x, y, toggle)
+ returnFunc(new, false)
+ end, 'Cancel', colours.black)
+ new.GoUpButton = Button:Initialise(2, new.Height - 1, nil, nil, colours.white, new, function(self, side, x, y, toggle)
+ local folderName = fs.getName(new.CurrentDirectory)
+ local parentDirectory = new.CurrentDirectory:sub(1, #new.CurrentDirectory-#folderName-1)
+ new:GoToDirectory(parentDirectory)
+ end, 'Go Up', colours.black)
+ new.PathTextBox = TextBox:Initialise(2, new.Height - 3, new.Width - 2, 1, new, new.CurrentDirectory, colours.white, colours.black)
+ new:GoToDirectory(new.CurrentDirectory)
+ return new
+ end,
+
+ Show = function(self)
+ Current.Window = self
+ return self
+ end,
+
+ Close = function(self)
+ Current.Input = nil
+ Current.Window = nil
+ self = nil
+ end,
+
+ GoToDirectory = function(self, path)
+ path = TidyPath(path)
+ self.CurrentDirectory = path
+ self.Scroll = 0
+ self.SelectedFile = nil
+ self.Typed = false
+ self.PathTextBox.TextInput.Value = path
+ local fs = fs
+ if OneOS then
+ fs = OneOS.FS
+ end
+ self.Files = fs.list(self.CurrentDirectory)
+ Draw()
+ end,
+
+ Flash = function(self)
+ self.Visible = false
+ Draw()
+ sleep(0.15)
+ self.Visible = true
+ Draw()
+ sleep(0.15)
+ self.Visible = false
+ Draw()
+ sleep(0.15)
+ self.Visible = true
+ Draw()
+ end,
+
+ Click = function(self, side, x, y)
+ local items = {self.OpenButton, self.CancelButton, self.PathTextBox, self.GoUpButton}
+ local found = false
+ for i, v in ipairs(items) do
+ if CheckClick(v, x, y) then
+ v:Click(side, x, y)
+ found = true
+ end
+ end
+
+ if not found then
+ if y <= 12 then
+ local fs = fs
+ if OneOS then
+ fs = OneOS.FS
+ end
+ self.SelectedFile = fs.list(self.CurrentDirectory)[y-1]
+ self.PathTextBox.TextInput.Value = TidyPath(self.CurrentDirectory .. '/' .. self.SelectedFile)
+ Draw()
+ end
+ end
+ return true
+ end
+}
+
+PrintDocumentWindow = {
+ X = 1,
+ Y = 1,
+ Width = 0,
+ Height = 0,
+ CursorPos = 1,
+ Visible = true,
+ Return = nil,
+ PrintButton = nil,
+ CopiesTextBox = nil,
+ Scroll = 0,
+ MaxScroll = 0,
+ PrinterSelectButton = nil,
+ Title = '',
+ Status = 0, --0 = neutral, 1 = good, -1 = error
+ StatusText = '',
+ SelectedPrinter = nil,
+
+ AbsolutePosition = function(self)
+ return {X = self.X, Y = self.Y}
+ end,
+
+ Draw = function(self)
+ if not self.Visible then
+ return
+ end
+ Drawing.DrawBlankArea(self.X + 1, self.Y+1, self.Width, self.Height, colours.grey)
+ Drawing.DrawBlankArea(self.X, self.Y, self.Width, 1, colours.lightGrey)
+ Drawing.DrawBlankArea(self.X, self.Y+1, self.Width, self.Height-1, colours.white)
+ Drawing.DrawCharactersCenter(self.X, self.Y, self.Width, 1, self.Title, colours.black, colours.lightGrey)
+
+ self.PrinterSelectButton:Draw()
+ Drawing.DrawCharactersCenter(self.X, self.Y + self.PrinterSelectButton.Y - 2, self.Width, 1, 'Printer', colours.black, colours.white)
+ Drawing.DrawCharacters(self.X + self.Width - 3, self.Y + self.PrinterSelectButton.Y - 1, '\\/', colours.black, colours.lightGrey)
+ Drawing.DrawCharacters(self.X + 1, self.Y + self.CopiesTextBox.Y - 1, 'Copies', colours.black, colours.white)
+ local statusColour = colours.grey
+ if self.Status == -1 then
+ statusColour = colours.red
+ elseif self.Status == 1 then
+ statusColour = colours.green
+ end
+ Drawing.DrawCharacters(self.X + 1, self.Y + self.CopiesTextBox.Y + 1, self.StatusText, statusColour, colours.white)
+
+ self.CopiesTextBox:Draw()
+ self.PrintButton:Draw()
+ self.CancelButton:Draw()
+ end,
+
+ Initialise = function(self)
+ local new = {} -- the new instance
+ setmetatable( new, {__index = self} )
+ new.Width = 32
+ new.Height = 11
+ new.Return = returnFunc
+ new.X = math.ceil((Drawing.Screen.Width - new.Width) / 2)
+ new.Y = math.ceil((Drawing.Screen.Height - new.Height) / 2)
+ new.Title = 'Print Document'
+ new.Visible = true
+ new.PrintButton = Button:Initialise(new.Width - 7, new.Height - 1, nil, nil, colours.lightGrey, new, function(self, side, x, y, toggle)
+ local doPrint = true
+ if new.SelectedPrinter == nil then
+ local p = Peripheral.GetPeripheral('printer')
+ if p then
+ new.SelectedPrinter = p.Side
+ new.PrinterSelectButton.Text = p.Fullname
+ else
+ new.StatusText = 'No Connected Printer'
+ new.Status = -1
+ doPrint = false
+ end
+ end
+ if doPrint then
+ local printer = Printer:Initialise(new.SelectedPrinter)
+ local err = printer:PrintLines(Current.Document.Lines, Current.Document.Title, tonumber(new.CopiesTextBox.TextInput.Value))
+ if not err then
+ new.StatusText = 'Document Printed!'
+ new.Status = 1
+ closeWindowTimer = os.startTimer(1)
+ else
+ new.StatusText = err
+ new.Status = -1
+ end
+ end
+ end, 'Print', colours.black)
+ new.CancelButton = Button:Initialise(new.Width - 15, new.Height - 1, nil, nil, colours.lightGrey, new, function(self, side, x, y, toggle)
+ new:Close()
+ Draw()
+ end, 'Close', colours.black)
+ new.PrinterSelectButton = Button:Initialise(2, 4, new.Width - 2, nil, colours.lightGrey, new, function(self, side, x, y, toggle)
+ local printers = {
+ {
+ Title = "Automatic",
+ Click = function()
+ new.SelectedPrinter = nil
+ new.PrinterSelectButton.Text = 'Automatic'
+ end
+ },
+ {
+ Separator = true
+ }
+ }
+ for i, p in ipairs(Peripheral.GetPeripherals('printer')) do
+ table.insert(printers, {
+ Title = p.Fullname,
+ Click = function(self)
+ new.SelectedPrinter = p.Side
+ new.PrinterSelectButton.Text = p.Fullname
+ end
+ })
+ end
+ Current.Menu = Menu:New(x, y+4, printers, self, true)
+ end, 'Automatic', colours.black)
+ new.CopiesTextBox = TextBox:Initialise(9, 6, 4, 1, new, 1, colours.lightGrey, colours.black, nil, true)
+ Current.TextInput = new.CopiesTextBox.TextInput
+ new.StatusText = 'Waiting...'
+ new.Status = 0
+ return new
+ end,
+
+ Show = function(self)
+ Current.Window = self
+ return self
+ end,
+
+ Close = function(self)
+ Current.Input = nil
+ Current.Window = nil
+ self = nil
+ end,
+
+ Flash = function(self)
+ self.Visible = false
+ Draw()
+ sleep(0.15)
+ self.Visible = true
+ Draw()
+ sleep(0.15)
+ self.Visible = false
+ Draw()
+ sleep(0.15)
+ self.Visible = true
+ Draw()
+ end,
+
+ Click = function(self, side, x, y)
+ local items = {self.PrintButton, self.CancelButton, self.CopiesTextBox, self.PrinterSelectButton}
+ for i, v in ipairs(items) do
+ if CheckClick(v, x, y) then
+ v:Click(side, x, y)
+ end
+ end
+ return true
+ end
+}
+
+SaveDocumentWindow = {
+ X = 1,
+ Y = 1,
+ Width = 0,
+ Height = 0,
+ CursorPos = 1,
+ Visible = true,
+ Return = nil,
+ SaveButton = nil,
+ PathTextBox = nil,
+ CurrentDirectory = '/',
+ Scroll = 0,
+ MaxScroll = 0,
+ ScrollBar = nil,
+ GoUpButton = nil,
+ Files = {},
+ Typed = false,
+
+ AbsolutePosition = function(self)
+ return {X = self.X, Y = self.Y}
+ end,
+
+ Draw = function(self)
+ if not self.Visible then
+ return
+ end
+ Drawing.DrawBlankArea(self.X + 1, self.Y+1, self.Width, self.Height, colours.grey)
+ Drawing.DrawBlankArea(self.X, self.Y, self.Width, 3, colours.lightGrey)
+ Drawing.DrawBlankArea(self.X, self.Y+1, self.Width, self.Height-6, colours.white)
+ Drawing.DrawCharactersCenter(self.X, self.Y, self.Width, 1, self.Title, colours.black, colours.lightGrey)
+ Drawing.DrawBlankArea(self.X, self.Y + self.Height - 5, self.Width, 5, colours.lightGrey)
+ Drawing.DrawCharacters(self.X + 1, self.Y + self.Height - 5, self.CurrentDirectory, colours.grey, colours.lightGrey)
+ self:DrawFiles()
+
+ if (self.PathTextBox.TextInput.Value) then
+ self.SaveButton.TextColour = colours.black
+ else
+ self.SaveButton.TextColour = colours.lightGrey
+ end
+
+ self.PathTextBox:Draw()
+ self.SaveButton:Draw()
+ self.CancelButton:Draw()
+ self.GoUpButton:Draw()
+ end,
+
+ DrawFiles = function(self)
+ for i, file in ipairs(self.Files) do
+ if i > self.Scroll and i - self.Scroll <= 10 then
+ if file == self.SelectedFile then
+ Drawing.DrawCharacters(self.X + 1, self.Y + i - self.Scroll, file, colours.white, colours.lightBlue)
+ elseif fs.isDir(self.CurrentDirectory .. file) then
+ Drawing.DrawCharacters(self.X + 1, self.Y + i - self.Scroll, file, colours.black, colours.white)
+ else
+ Drawing.DrawCharacters(self.X + 1, self.Y + i - self.Scroll, file, colours.lightGrey, colours.white)
+ end
+ end
+ end
+ self.MaxScroll = #self.Files - 11
+ if self.MaxScroll < 0 then
+ self.MaxScroll = 0
+ end
+ end,
+
+ Initialise = function(self, returnFunc)
+ local new = {} -- the new instance
+ setmetatable( new, {__index = self} )
+ new.Width = 32
+ new.Height = 16
+ new.Return = returnFunc
+ new.X = math.ceil((Drawing.Screen.Width - new.Width) / 2)
+ new.Y = math.ceil((Drawing.Screen.Height - new.Height) / 2)
+ new.Title = 'Save Document'
+ new.Visible = true
+ new.CurrentDirectory = '/'
+ if OneOS and fs.exists('/Desktop/Documents/') then
+ new.CurrentDirectory = '/Desktop/Documents/'
+ end
+ new.SaveButton = Button:Initialise(new.Width - 6, new.Height - 1, nil, nil, colours.white, new, function(self, side, x, y, toggle)
+ if self.TextColour == colours.black and not fs.isDir(new.CurrentDirectory ..'/' .. new.PathTextBox.TextInput.Value) then
+ returnFunc(new, true, TidyPath(new.CurrentDirectory ..'/' .. new.PathTextBox.TextInput.Value))
+ elseif new.SelectedFile and self.TextColour == colours.black and fs.isDir(new.CurrentDirectory .. new.SelectedFile) then
+ new:GoToDirectory(new.CurrentDirectory .. new.SelectedFile)
+ end
+ end, 'Save', colours.black)
+ new.CancelButton = Button:Initialise(new.Width - 15, new.Height - 1, nil, nil, colours.white, new, function(self, side, x, y, toggle)
+ returnFunc(new, false)
+ end, 'Cancel', colours.black)
+ new.GoUpButton = Button:Initialise(2, new.Height - 1, nil, nil, colours.white, new, function(self, side, x, y, toggle)
+ local folderName = fs.getName(new.CurrentDirectory)
+ local parentDirectory = new.CurrentDirectory:sub(1, #new.CurrentDirectory-#folderName-1)
+ new:GoToDirectory(parentDirectory)
+ end, 'Go Up', colours.black)
+ new.PathTextBox = TextBox:Initialise(2, new.Height - 3, new.Width - 2, 1, new, '', colours.white, colours.black, function(key)
+ if key == keys.enter then
+ new.SaveButton:Click()
+ end
+ end)
+ new.PathTextBox.Placeholder = 'Document Name'
+ Current.TextInput = new.PathTextBox.TextInput
+ new:GoToDirectory(new.CurrentDirectory)
+ return new
+ end,
+
+ Show = function(self)
+ Current.Window = self
+ return self
+ end,
+
+ Close = function(self)
+ Current.Input = nil
+ Current.Window = nil
+ self = nil
+ end,
+
+ GoToDirectory = function(self, path)
+ path = TidyPath(path)
+ self.CurrentDirectory = path
+ self.Scroll = 0
+ self.Typed = false
+ local fs = fs
+ if OneOS then
+ fs = OneOS.FS
+ end
+ self.Files = fs.list(self.CurrentDirectory)
+ Draw()
+ end,
+
+ Flash = function(self)
+ self.Visible = false
+ Draw()
+ sleep(0.15)
+ self.Visible = true
+ Draw()
+ sleep(0.15)
+ self.Visible = false
+ Draw()
+ sleep(0.15)
+ self.Visible = true
+ Draw()
+ end,
+
+ Click = function(self, side, x, y)
+ local items = {self.SaveButton, self.CancelButton, self.PathTextBox, self.GoUpButton}
+ local found = false
+ for i, v in ipairs(items) do
+ if CheckClick(v, x, y) then
+ v:Click(side, x, y)
+ found = true
+ end
+ end
+
+ if not found then
+ if y <= 11 then
+ local files = fs.list(self.CurrentDirectory)
+ if files[y-1] then
+ self:GoToDirectory(self.CurrentDirectory..files[y-1])
+ Draw()
+ end
+ end
+ end
+ return true
+ end
+}
+
+local WrapText = function(text, maxWidth)
+ local lines = {''}
+ for word, space in text:gmatch('(%S+)(%s*)') do
+ local temp = lines[#lines] .. word .. space:gsub('\n','')
+ if #temp > maxWidth then
+ table.insert(lines, '')
+ end
+ if space:find('\n') then
+ lines[#lines] = lines[#lines] .. word
+
+ space = space:gsub('\n', function()
+ table.insert(lines, '')
+ return ''
+ end)
+ else
+ lines[#lines] = lines[#lines] .. word .. space
+ end
+ end
+ return lines
+end
+
+ButtonDialougeWindow = {
+ X = 1,
+ Y = 1,
+ Width = 0,
+ Height = 0,
+ CursorPos = 1,
+ Visible = true,
+ CancelButton = nil,
+ OkButton = nil,
+ Lines = {},
+
+ AbsolutePosition = function(self)
+ return {X = self.X, Y = self.Y}
+ end,
+
+ Draw = function(self)
+ if not self.Visible then
+ return
+ end
+ Drawing.DrawBlankArea(self.X + 1, self.Y+1, self.Width, self.Height, colours.grey)
+ Drawing.DrawBlankArea(self.X, self.Y, self.Width, 1, colours.lightGrey)
+ Drawing.DrawBlankArea(self.X, self.Y+1, self.Width, self.Height-1, colours.white)
+ Drawing.DrawCharactersCenter(self.X, self.Y, self.Width, 1, self.Title, colours.black, colours.lightGrey)
+
+ for i, text in ipairs(self.Lines) do
+ Drawing.DrawCharacters(self.X + 1, self.Y + 1 + i, text, colours.black, colours.white)
+ end
+
+ self.OkButton:Draw()
+ if self.CancelButton then
+ self.CancelButton:Draw()
+ end
+ end,
+
+ Initialise = function(self, title, message, okText, cancelText, returnFunc)
+ local new = {} -- the new instance
+ setmetatable( new, {__index = self} )
+ new.Width = 28
+ new.Lines = WrapText(message, new.Width - 2)
+ new.Height = 5 + #new.Lines
+ new.Return = returnFunc
+ new.X = math.ceil((Drawing.Screen.Width - new.Width) / 2)
+ new.Y = math.ceil((Drawing.Screen.Height - new.Height) / 2)
+ new.Title = title
+ new.Visible = true
+ new.Visible = true
+ new.OkButton = Button:Initialise(new.Width - #okText - 2, new.Height - 1, nil, 1, nil, new, function()
+ returnFunc(new, true)
+ end, okText)
+ if cancelText then
+ new.CancelButton = Button:Initialise(new.Width - #okText - 2 - 1 - #cancelText - 2, new.Height - 1, nil, 1, nil, new, function()
+ returnFunc(new, false)
+ end, cancelText)
+ end
+
+ return new
+ end,
+
+ Show = function(self)
+ Current.Window = self
+ return self
+ end,
+
+ Close = function(self)
+ Current.Window = nil
+ self = nil
+ end,
+
+ Flash = function(self)
+ self.Visible = false
+ Draw()
+ sleep(0.15)
+ self.Visible = true
+ Draw()
+ sleep(0.15)
+ self.Visible = false
+ Draw()
+ sleep(0.15)
+ self.Visible = true
+ Draw()
+ end,
+
+ Click = function(self, side, x, y)
+ local items = {self.OkButton, self.CancelButton}
+ local found = false
+ for i, v in ipairs(items) do
+ if CheckClick(v, x, y) then
+ v:Click(side, x, y)
+ found = true
+ end
+ end
+ return true
+ end
+}
+
+TextDialougeWindow = {
+ X = 1,
+ Y = 1,
+ Width = 0,
+ Height = 0,
+ CursorPos = 1,
+ Visible = true,
+ CancelButton = nil,
+ OkButton = nil,
+ Lines = {},
+ TextInput = nil,
+
+ AbsolutePosition = function(self)
+ return {X = self.X, Y = self.Y}
+ end,
+
+ Draw = function(self)
+ if not self.Visible then
+ return
+ end
+ Drawing.DrawBlankArea(self.X + 1, self.Y+1, self.Width, self.Height, colours.grey)
+ Drawing.DrawBlankArea(self.X, self.Y, self.Width, 1, colours.lightGrey)
+ Drawing.DrawBlankArea(self.X, self.Y+1, self.Width, self.Height-1, colours.white)
+ Drawing.DrawCharactersCenter(self.X, self.Y, self.Width, 1, self.Title, colours.black, colours.lightGrey)
+
+ for i, text in ipairs(self.Lines) do
+ Drawing.DrawCharacters(self.X + 1, self.Y + 1 + i, text, colours.black, colours.white)
+ end
+
+
+ Drawing.DrawBlankArea(self.X + 1, self.Y + self.Height - 4, self.Width - 2, 1, colours.lightGrey)
+ Drawing.DrawCharacters(self.X + 2, self.Y + self.Height - 4, self.TextInput.Value, colours.black, colours.lightGrey)
+ Current.CursorPos = {self.X + 2 + self.TextInput.CursorPos, self.Y + self.Height - 4}
+ Current.CursorColour = colours.black
+
+ self.OkButton:Draw()
+ if self.CancelButton then
+ self.CancelButton:Draw()
+ end
+ end,
+
+ Initialise = function(self, title, message, okText, cancelText, returnFunc, numerical)
+ local new = {} -- the new instance
+ setmetatable( new, {__index = self} )
+ new.Width = 28
+ new.Lines = WrapText(message, new.Width - 2)
+ new.Height = 7 + #new.Lines
+ new.Return = returnFunc
+ new.X = math.ceil((Drawing.Screen.Width - new.Width) / 2)
+ new.Y = math.ceil((Drawing.Screen.Height - new.Height) / 2)
+ new.Title = title
+ new.Visible = true
+ new.Visible = true
+ new.OkButton = Button:Initialise(new.Width - #okText - 2, new.Height - 1, nil, 1, nil, new, function()
+ if #new.TextInput.Value > 0 then
+ returnFunc(new, true, new.TextInput.Value)
+ end
+ end, okText)
+ if cancelText then
+ new.CancelButton = Button:Initialise(new.Width - #okText - 2 - 1 - #cancelText - 2, new.Height - 1, nil, 1, nil, new, function()
+ returnFunc(new, false)
+ end, cancelText)
+ end
+ new.TextInput = TextInput:Initialise('', function(enter)
+ if enter then
+ new.OkButton:Click()
+ end
+ Draw()
+ end, numerical)
+
+ Current.Input = new.TextInput
+
+ return new
+ end,
+
+ Show = function(self)
+ Current.Window = self
+ return self
+ end,
+
+ Close = function(self)
+ Current.Window = nil
+ Current.Input = nil
+ self = nil
+ end,
+
+ Flash = function(self)
+ self.Visible = false
+ Draw()
+ sleep(0.15)
+ self.Visible = true
+ Draw()
+ sleep(0.15)
+ self.Visible = false
+ Draw()
+ sleep(0.15)
+ self.Visible = true
+ Draw()
+ end,
+
+ Click = function(self, side, x, y)
+ local items = {self.OkButton, self.CancelButton}
+ local found = false
+ for i, v in ipairs(items) do
+ if CheckClick(v, x, y) then
+ v:Click(side, x, y)
+ found = true
+ end
+ end
+ return true
+ end
+}
+
+function PrintCentered(text, y)
+ local w, h = term.getSize()
+ x = math.ceil(math.ceil((w / 2) - (#text / 2)), 0)+1
+ term.setCursorPos(x, y)
+ print(text)
+end
+
+function DoVanillaClose()
+ term.setBackgroundColour(colours.black)
+ term.setTextColour(colours.white)
+ term.clear()
+ term.setCursorPos(1, 1)
+ PrintCentered("Thanks for using Ink!", (Drawing.Screen.Height/2)-1)
+ term.setTextColour(colours.lightGrey)
+ PrintCentered("Word Proccessor for ComputerCraft", (Drawing.Screen.Height/2))
+ term.setTextColour(colours.white)
+ PrintCentered("(c) oeed 2014", (Drawing.Screen.Height/2)+3)
+ term.setCursorPos(1, Drawing.Screen.Height)
+ error('', 0)
+end
+
+function Close()
+ if isQuitting or not Current.Document or not Current.Modified then
+ if not OneOS then
+ DoVanillaClose()
+ end
+ return true
+ else
+ local _w = ButtonDialougeWindow:Initialise('Quit Ink?', 'You have unsaved changes, do you want to quit anyway?', 'Quit', 'Cancel', function(window, success)
+ if success then
+ if OneOS then
+ OneOS.Close(true)
+ else
+ DoVanillaClose()
+ end
+ end
+ window:Close()
+ Draw()
+ end):Show()
+ --it's hacky but it works
+ os.queueEvent('mouse_click', 1, _w.X, _w.Y)
+ return false
+ end
+end
+
+if OneOS then
+ OneOS.CanClose = function()
+ return Close()
+ end
+end
+
+Initialise() \ No newline at end of file