This commit is contained in:
Igor Timofeev 2016-06-07 08:40:02 +03:00
parent 135ac5a578
commit 33d8f23973
4 changed files with 146 additions and 78 deletions

View File

@ -249,7 +249,7 @@
["name"]="lib/GUI.lua",
["url"]="IgorTimofeev/OpenComputers/master/lib/GUI.lua",
["type"]="Library",
["version"]=1.0,
["version"]=1.1,
},
{
["name"]="lib/serialization.lua",
@ -351,7 +351,7 @@
["name"]="lib/doubleBuffering.lua",
["url"]="IgorTimofeev/OpenComputers/master/lib/doubleBuffering.lua",
["type"]="Library",
["version"]=1.0,
["version"]=1.1,
},
{
["name"]="lib/thread.lua",
@ -578,7 +578,7 @@
["icon"]="IgorTimofeev/OpenComputers/master/Applications/AppMarket/Icon.pic",
["createShortcut"]="dock",
["forceDownload"]=true,
["version"]=1.34,
["version"]=1.35,
},
{
["name"]="MineOS/Applications/Snake",

View File

@ -1,4 +1,7 @@
package.loaded.GUI = nil
_G.GUI = nil
local libraries = {
buffer = "doubleBuffering",
MineOSCore = "MineOSCore",
@ -48,8 +51,7 @@ local pathToApplications = "MineOS/System/OS/Applications.txt"
local updateImage = image.load(MineOSCore.paths.icons .. "Update.pic")
-- local topBarElements = {{title = "Приложения", type = "Application"}, {title = "Библиотеки", type = "Library"}, {title = "Обои", type = "Wallpaper"}, {title = "Другое"}, {title = "Обновления"}}
local topBarElements = {"Приложения", "Библиотеки", "Обои", "Другое", "Обновления"}
local oldApplications, newApplications, changes = {}, {}, {}
local currentApps = {}
local oldApplications, newApplications, currentApps, changes = {}, {}, {}, {}
local currentTopBarElement = 1
local from, limit, fromY = 1, 8
@ -72,10 +74,11 @@ local function calculateSizes()
sizes.width, sizes.height = math.floor(buffer.screen.width * 0.6), math.floor(buffer.screen.height * 0.7)
sizes.x, sizes.y = math.floor(buffer.screen.width / 2 - sizes.width / 2), math.floor(buffer.screen.height / 2 - sizes.height / 2)
sizes.topBarHeight = 3
sizes.yMain = sizes.y + sizes.topBarHeight
sizes.mainHeight = sizes.height - sizes.topBarHeight
obj.main = GUI.object(sizes.x, sizes.y + sizes.topBarHeight, sizes.width, sizes.height - sizes.topBarHeight)
sizes.downloadButtonWidth = 17
sizes.descriptionTruncateSize = sizes.width - 6 - MineOSCore.iconWidth - sizes.downloadButtonWidth
sizes.searchFieldWidth = math.floor(sizes.width * 0.3)
obj.searchTextField = GUI.textField(math.floor(sizes.x + sizes.width / 2 - sizes.searchFieldWidth / 2), 1, sizes.searchFieldWidth, 1, 0xEEEEEE, 0x777777, 0xEEEEEE, 0x555555, nil, "Поиск", false, true)
end
local function drawTopBar()
@ -184,26 +187,33 @@ local function drawPageSwitchButtons(y)
end
local function clearMainZone()
buffer.square(sizes.x, sizes.yMain, sizes.width, sizes.mainHeight, 0xFFFFFF)
buffer.square(sizes.x, obj.main.y, sizes.width, obj.main.height, 0xFFFFFF)
end
local function drawMain(refreshData)
clearMainZone()
local x, y = sizes.x + 2, fromY
buffer.setDrawLimit(sizes.x, sizes.yMain, sizes.width, sizes.mainHeight)
buffer.setDrawLimit(sizes.x, obj.main.y, sizes.width, obj.main.height)
obj.searchTextField.y, obj.searchTextField.invisible = y, false
obj.searchTextField:draw()
y = y + 2
local matchCount = 1
for i = 1, #newApplications do
if newApplications[i].type == typeFilters[currentTopBarElement] then
if matchCount >= from and matchCount <= from + limit - 1 then
if refreshData and not currentApps[i] then
status("Загрузка информации о приложении \"" .. newApplications[i].name .. "\"")
getApplication(i)
-- if obj.searchTextField.text then GUI.error(tostring(unicode.lower(obj.searchTextField.text))) end
if not obj.searchTextField.text or (string.find(unicode.lower(fs.name(newApplications[i].name)), unicode.lower(obj.searchTextField.text))) then
if matchCount >= from and matchCount <= from + limit - 1 then
if refreshData and not currentApps[i] then
status("Загрузка информации о приложении \"" .. newApplications[i].name .. "\"")
getApplication(i)
end
x, y = drawApplication(x, y, i)
end
x, y = drawApplication(x, y, i)
matchCount = matchCount + 1
end
matchCount = matchCount + 1
end
end
@ -226,8 +236,7 @@ local function getChanges()
for j = 1, #newApplications do
if oldApplications[i].name == newApplications[j].name then
if oldApplications[i].version < newApplications[j].version then
table.insert(changes, newApplications[j])
changes[#changes].newApplicationsIndex = j
table.insert(changes, j)
end
end
end
@ -238,18 +247,18 @@ local function updates()
clearMainZone()
if #changes > 0 then
buffer.setDrawLimit(sizes.x, sizes.yMain, sizes.width, sizes.mainHeight)
buffer.setDrawLimit(sizes.x, obj.main.y, sizes.width, obj.main.height)
local x, y = sizes.x + 2, fromY
obj.updateAllButton = GUI.button(math.floor(sizes.x + sizes.width / 2 - sizes.downloadButtonWidth / 2), y, 20, 1, colors.downloadButton, colors.downloadButtonText, 0x555555, 0xFFFFFF, "Обновить все")
y = y + 2
for i = from, (from + limit) do
if not changes[i] then break end
if not currentApps[changes[i].newApplicationsIndex] then
status("Загрузка информации о приложении \"" .. changes[i].name .. "\"")
getApplication(changes[i].newApplicationsIndex)
if not currentApps[changes[i]] then
status("Загрузка информации о приложении \"" .. fs.name(newApplications[changes[i]].name) .. "\"")
getApplication(changes[i])
end
x, y = drawApplication(x, y, changes[i].newApplicationsIndex, true)
x, y = drawApplication(x, y, changes[i], true)
end
if #changes > limit then
@ -258,12 +267,12 @@ local function updates()
buffer.resetDrawLimit()
else
local text = "У вас самое новое ПО"
buffer.text(math.floor(sizes.x + sizes.width / 2 - unicode.len(text) / 2), math.floor(sizes.yMain + sizes.mainHeight / 2 - 1), colors.description, text)
buffer.text(math.floor(sizes.x + sizes.width / 2 - unicode.len(text) / 2), math.floor(obj.main.y + obj.main.height / 2 - 1), colors.description, text)
end
end
local function flush()
fromY = sizes.yMain + 1
fromY = obj.main.y + 1
from = 1
fs.makeDirectory(appStorePath)
currentApps = {}
@ -289,7 +298,7 @@ end
local function updateImageWindow()
clearMainZone()
local x, y = math.floor(sizes.x + sizes.width / 2 - updateImage.width / 2), math.floor(sizes.yMain + sizes.mainHeight / 2 - updateImage.height / 2 - 2)
local x, y = math.floor(sizes.x + sizes.width / 2 - updateImage.width / 2), math.floor(obj.main.y + obj.main.height / 2 - updateImage.height / 2 - 2)
buffer.image(x, y, updateImage)
return y + updateImage.height
end
@ -306,13 +315,13 @@ local function updateAll()
local xBar = math.floor(sizes.x + sizes.width / 2 - barWidth / 2)
y = y + 2
for i = 1, #changes do
local text = "Обновление " .. fs.name(changes[i].name)
local text = "Обновление " .. fs.name(newApplications[changes[i]].name)
local xText = math.floor(sizes.x + sizes.width / 2 - unicode.len(text) / 2)
buffer.square(sizes.x, y + 1, sizes.width, 1, 0xFFFFFF)
buffer.text(xText, y + 1, colors.description, text)
GUI.progressBar(xBar, y, barWidth, 1, 0xAAAAAA, 0x55FF55, i, #changes, true)
buffer.draw()
ecs.getOSApplication(newApplications[changes[i].newApplicationsIndex], true)
ecs.getOSApplication(newApplications[changes[i]], true)
end
changes = {}
oldApplications = newApplications
@ -321,8 +330,8 @@ end
------------------------------------------------------------------------------------------------------------------
-- buffer.start()
-- buffer.clear(0xFF8888)
buffer.start()
buffer.clear(0xFF8888)
local args = {...}
if args[1] == "updateCheck" then
@ -343,50 +352,60 @@ drawAll(true, false)
while true do
local e = {event.pull()}
if e[1] == "touch" then
if currentTopBarElement < 5 then
for appIndex, app in pairs(currentApps) do
if app.buttonObject:isClicked(e[3], e[4]) then
app.buttonObject:press(0.3)
if app.buttonObject.text == "Обновить" or app.buttonObject.text == "Загрузить" then
app.buttonObject.text = "Загрузка"
app.buttonObject.disabled = true
app.buttonObject.colors.disabled.button, app.buttonObject.colors.disabled.text = colors.downloading, colors.downloadingText
app.buttonObject:draw()
buffer.draw()
ecs.getOSApplication(newApplications[appIndex], true)
app.buttonObject.text = "Установлено"
app.buttonObject.colors.disabled.button, app.buttonObject.colors.disabled.text = colors.downloaded, colors.downloadedText
app.buttonObject:draw()
buffer.draw()
if obj.main:isClicked(e[3], e[4]) then
if obj.searchTextField:isClicked(e[3], e[4]) then
obj.searchTextField:input()
flush()
drawAll(true, false)
end
if currentTopBarElement < 5 then
for appIndex, app in pairs(currentApps) do
if app.buttonObject:isClicked(e[3], e[4]) then
app.buttonObject:press(0.3)
if app.buttonObject.text == "Обновить" or app.buttonObject.text == "Загрузить" then
app.buttonObject.text = "Загрузка"
app.buttonObject.disabled = true
app.buttonObject.colors.disabled.button, app.buttonObject.colors.disabled.text = colors.downloading, colors.downloadingText
app.buttonObject:draw()
buffer.draw()
ecs.getOSApplication(newApplications[appIndex], true)
app.buttonObject.text = "Установлено"
app.buttonObject.colors.disabled.button, app.buttonObject.colors.disabled.text = colors.downloaded, colors.downloadedText
app.buttonObject:draw()
buffer.draw()
end
break
end
break
end
else
if obj.updateAllButton and obj.updateAllButton:isClicked(e[3], e[4]) then
obj.updateAllButton:press()
updateAll()
flush()
drawAll()
end
end
else
if obj.updateAllButton and obj.updateAllButton:isClicked(e[3], e[4]) then
obj.updateAllButton:press()
updateAll()
flush()
drawAll()
if obj.nextPageButton then
if obj.nextPageButton:isClicked(e[3], e[4]) then
obj.nextPageButton:press()
fromY = obj.main.y + 1
from = from + limit
currentApps = {}
drawAll(true, false)
elseif obj.prevPageButton:isClicked(e[3], e[4]) then
if from > limit then
fromY = obj.main.y + 1
from = from - limit
currentApps = {}
drawAll(true, false)
end
end
end
end
if obj.nextPageButton then
if obj.nextPageButton:isClicked(e[3], e[4]) then
obj.nextPageButton:press()
fromY = sizes.yMain + 1
from = from + limit
currentApps = {}
drawAll(true, false)
elseif obj.prevPageButton:isClicked(e[3], e[4]) then
if from > limit then
fromY = sizes.yMain + 1
from = from - limit
currentApps = {}
drawAll(true, false)
end
end
end
if obj.windowActionButtons.close:isClicked(e[3], e[4]) then
obj.windowActionButtons.close:press()
@ -403,7 +422,7 @@ while true do
end
elseif e[1] == "scroll" then
if e[5] == 1 then
if (fromY < sizes.yMain) then
if (fromY < obj.main.y) then
fromY = fromY + 2
drawAll(false, false)
end

View File

@ -2,7 +2,8 @@
local libraries = {
buffer = "doubleBuffering",
ecs = "ECSAPI",
unicode = "unicode"
unicode = "unicode",
event = "event",
}
for library in pairs(libraries) do if not _G[library] then _G[library] = require(libraries[library]) end end; libraries = nil
@ -24,11 +25,12 @@ GUI.buttonTypes = {
GUI.colors = {
disabled = 0x888888,
disabledText = 0xAAAAAA,
}
-- Универсальный метод для проверки клика на прямоугольный объект
local function objectClicked(object, x, y)
if x >= object.x and y >= object.y and x <= object.x + object.width - 1 and y <= object.y + object.height - 1 and not object.disabled then return true end
if x >= object.x and y >= object.y and x <= object.x + object.width - 1 and y <= object.y + object.height - 1 and not object.disabled and not object.invisible ~= false then return true end
return false
end
@ -91,7 +93,7 @@ local function createButtonObject(buttonType, x, y, width, height, buttonColor,
},
disabled = {
button = GUI.colors.disabled,
text = GUI.colors.disabled,
text = GUI.colors.disabledText,
}
}
buttonObject.disabled = disabledState
@ -329,6 +331,8 @@ end
-- }
function GUI.input(x, y, width, foreground, startText, textFieldProperties)
if not (y >= buffer.drawLimit.y and y <= buffer.drawLimit.y2) then return startText end
local text = startText
local textLength = unicode.len(text)
local cursorBlinkState = false
@ -424,6 +428,51 @@ function GUI.input(x, y, width, foreground, startText, textFieldProperties)
end
end
local function drawTextField(object, isFocused)
if not object.invisible then
local background = object.disabled and object.colors.disabled.textField or (isFocused and object.colors.focused.textField or object.colors.default.textField)
local foreground = object.disabled and object.colors.disabled.text or (isFocused and object.colors.focused.text or object.colors.default.text)
local y = math.floor(object.y + object.height / 2)
local text = isFocused and (object.text or "") or (object.text or object.placeholderText or "")
if background then buffer.square(object.x, object.y, object.width, object.height, background, foreground, " ") end
local resultText = GUI.input(object.x + 1, y, object.width - 2, foreground, text, {justDrawNotEvent = not isFocused})
object.text = isFocused and resultText or object.text
end
end
local function textFieldBeginInput(object)
drawTextField(object, true)
if object.text == "" then object.text = nil; drawTextField(object, false); buffer.draw() end
end
function GUI.textField(x, y, width, height, textFieldColor, textColor, textFieldFocusedColor, textFocusedColor, text, placeholderText, disabledState, invisibleState)
local object = GUI.object(x, y, width, height)
object.invisible = invisibleState
object.disabled = disabledState
object.colors = {
default = {
textField = textFieldColor,
text = textColor
},
focused = {
textField = textFieldFocusedColor,
text = textFocusedColor
},
disabled = {
textField = GUI.colors.disabled,
text = GUI.colors.disabledText,
}
}
object.text = text
object.placeholderText = placeholderText
object.isClicked = objectClicked
object.draw = drawTextField
object.input = textFieldBeginInput
object:draw()
return object
end
--------------------------------------------------------------------------------------------------------------------------------

View File

@ -51,12 +51,12 @@ end
-- Установить ограниченную зону рисования. Все пиксели, не попадающие в эту зону, будут игнорироваться.
function buffer.setDrawLimit(x, y, width, height)
buffer.drawLimit = { x1 = x, y1 = y, x2 = x + width - 1, y2 = y + height - 1 }
buffer.drawLimit = { x = x, y = y, x2 = x + width - 1, y2 = y + height - 1 }
end
-- Удалить ограничение зоны рисования, по умолчанию она будет от 1х1 до координат размера экрана.
function buffer.resetDrawLimit()
buffer.drawLimit = {x1 = 1, y1 = 1, x2 = buffer.screen.width, y2 = buffer.screen.height}
buffer.drawLimit = {x = 1, y = 1, x2 = buffer.screen.width, y2 = buffer.screen.height}
end
-- Создать массив буфера с базовыми переменными и базовыми цветами. Т.е. черный фон, белый текст.
@ -96,7 +96,7 @@ end
-- Установить пиксель в буфере
function buffer.set(x, y, background, foreground, symbol)
local index = convertCoordsToIndex(x, y)
if x >= buffer.drawLimit.x1 and y >= buffer.drawLimit.y1 and x <= buffer.drawLimit.x2 and y <= buffer.drawLimit.y2 then
if x >= buffer.drawLimit.x and y >= buffer.drawLimit.y and x <= buffer.drawLimit.x2 and y <= buffer.drawLimit.y2 then
buffer.screen.new[index] = background
buffer.screen.new[index + 1] = foreground
buffer.screen.new[index + 2] = symbol
@ -113,7 +113,7 @@ function buffer.square(x, y, width, height, background, foreground, symbol, tran
for j = y, (y + height - 1) do
for i = x, (x + width - 1) do
if i >= buffer.drawLimit.x1 and j >= buffer.drawLimit.y1 and i <= buffer.drawLimit.x2 and j <= buffer.drawLimit.y2 then
if i >= buffer.drawLimit.x and j >= buffer.drawLimit.y and i <= buffer.drawLimit.x2 and j <= buffer.drawLimit.y2 then
index = convertCoordsToIndex(i, j)
indexPlus1 = index + 1
indexPlus2 = index + 2
@ -156,7 +156,7 @@ function buffer.fill(x, y, background, foreground, symbol)
end
--Заливаем в память
if xStart >= buffer.drawLimit.x1 and yStart >= buffer.drawLimit.y1 and xStart <= buffer.drawLimit.x2 and yStart <= buffer.drawLimit.y2 then
if xStart >= buffer.drawLimit.x and yStart >= buffer.drawLimit.y and xStart <= buffer.drawLimit.x2 and yStart <= buffer.drawLimit.y2 then
buffer.screen.new[index] = background
buffer.screen.new[index + 1] = foreground
buffer.screen.new[index + 2] = symbol
@ -242,7 +242,7 @@ function buffer.paste(x, y, copyArray)
for j = y, (y + copyArray.height - 1) do
for i = x, (x + copyArray.width - 1) do
if i >= buffer.drawLimit.x1 and j >= buffer.drawLimit.y1 and i <= buffer.drawLimit.x2 and j <= buffer.drawLimit.y2 then
if i >= buffer.drawLimit.x and j >= buffer.drawLimit.y and i <= buffer.drawLimit.x2 and j <= buffer.drawLimit.y2 then
--Рассчитываем индекс массива основного изображения
index = convertCoordsToIndex(i, j)
--Копипаст формулы, аккуратнее!
@ -292,7 +292,7 @@ function buffer.text(x, y, color, text, transparency)
if transparency then transparency = transparency * 2.55 end
local sText = unicode.len(text)
for i = 1, sText do
if (x + i - 1) >= buffer.drawLimit.x1 and y >= buffer.drawLimit.y1 and (x + i - 1) <= buffer.drawLimit.x2 and y <= buffer.drawLimit.y2 then
if (x + i - 1) >= buffer.drawLimit.x and y >= buffer.drawLimit.y and (x + i - 1) <= buffer.drawLimit.x2 and y <= buffer.drawLimit.y2 then
index = convertCoordsToIndex(x + i - 1, y)
buffer.screen.new[index + 1] = not transparency and color or colorlib.alphaBlend(buffer.screen.new[index], color, transparency)
buffer.screen.new[index + 2] = unicode.sub(text, i, i)
@ -307,7 +307,7 @@ function buffer.image(x, y, picture)
for j = y, (y + picture.height - 1) do
for i = x, (x + picture.width - 1) do
if i >= buffer.drawLimit.x1 and j >= buffer.drawLimit.y1 and i <= buffer.drawLimit.x2 and j <= buffer.drawLimit.y2 then
if i >= buffer.drawLimit.x and j >= buffer.drawLimit.y and i <= buffer.drawLimit.x2 and j <= buffer.drawLimit.y2 then
index = convertCoordsToIndex(i, j)
indexPlus1 = index + 1
indexPlus2 = index + 2