From b84d8f084e9f4f33ee24904ab3382130de96b239 Mon Sep 17 00:00:00 2001 From: IgorTimofeev Date: Tue, 24 Oct 2023 16:04:46 +0300 Subject: [PATCH] =?UTF-8?q?=D0=A2=D0=B0=D0=B1=D0=BB=D0=B8=D1=87=D0=BA?= =?UTF-8?q?=D0=B8=20=D1=87=D1=83=D1=82=D1=8C=20=D0=BF=D0=BE=D0=BB=D1=83?= =?UTF-8?q?=D1=87=D1=88=D0=B5=20=D1=81=D0=B4=D0=B5=D0=BB=D0=B0=D0=BB?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- Applications/Finder.app/Main.lua | 102 ++- Applications/Picture Edit.app/Tools/1.lua | 4 +- .../Pioneer.app/Images/Background.pic | Bin 15042 -> 14528 bytes Applications/Pioneer.app/Main.lua | 837 +++++++++++------- Libraries/GUI.lua | 125 ++- Libraries/System.lua | 63 +- 6 files changed, 664 insertions(+), 467 deletions(-) diff --git a/Applications/Finder.app/Main.lua b/Applications/Finder.app/Main.lua index f9d63456..4220b8ec 100644 --- a/Applications/Finder.app/Main.lua +++ b/Applications/Finder.app/Main.lua @@ -80,7 +80,7 @@ itemsLayout:setMargin(1, 1, 0, 0) local searchInput = window:addChild(GUI.input(1, 2, 16, 1, 0x4B4B4B, 0xC3C3C3, 0x878787, 0x4B4B4B, 0xE1E1E1, nil, localization.search, true)) -local iconField +local iconField local statusContainer = window:addChild(GUI.container(FTPButton.localX + FTPButton.width + 2, 2, 1, 1)) local statusPanel = statusContainer:addChild(GUI.panel(1, 1, 1, 1, 0x4B4B4B)) @@ -97,8 +97,42 @@ local function saveConfig() filesystem.writeTable(configPath, config) end +local function getVerticalScroll() + return config.gridMode and iconField.yOffset or iconField:getVerticalScroll() +end + +local function setVerticalScroll(value) + if config.gridMode then + local iconsCount = #iconField.children + local rows = math.ceil((iconsCount - 1) / iconField.iconCount.horizontal) + local minimumOffset = (rows - 1) * (userSettings.iconHeight + userSettings.iconVerticalSpace) - userSettings.iconVerticalSpace + + value = math.max(-minimumOffset + 1, math.min(iconField.initialYOffset, value)) + + local delta = iconField.yOffset - value + iconField.yOffset = value + + local iconsCount, child = #iconField.children + + if iconsCount < 2 then + return + end + + for i = 1, iconsCount do + child = iconField.children[i] + + if child ~= iconField.backgroundObject then + child.localY = child.localY - delta + end + end + else + iconField:setVerticalScroll(value) + end +end + local function updateFileListAndDraw() iconField:updateFileList() + setVerticalScroll(config.gridMode and iconField.initialYOffset or 0) workspace:draw() end @@ -124,9 +158,11 @@ local function prevOrNextpath(next) updateFileListAndDraw() end -local function addpath(path) +local function addPath(path) pathHistoryCurrent = pathHistoryCurrent + 1 + table.insert(pathHistory, pathHistoryCurrent, path) + for i = pathHistoryCurrent + 1, #pathHistory do pathHistory[i] = nil end @@ -187,7 +223,7 @@ local function addSidebarSeparator() end local function onFavouriteTouch(path) - addpath(path) + addPath(path) updateFileListAndDraw() end @@ -196,7 +232,7 @@ local openFTP, updateSidebar openFTP = function(...) local mountPath = FTPMountPath .. network.getFTPProxyName(...) .. "/" - addpath(mountPath) + addPath(mountPath) workspace:draw() local proxy, reason = network.connectToFTP(...) @@ -243,7 +279,7 @@ updateSidebar = function() end addSidebarItem(" " .. network.getModemProxyName(proxy), path).onTouch = function() - addpath(path) + addPath(path) updateFileListAndDraw() end end @@ -436,59 +472,47 @@ local function updateIconField() ) or system.listIconField( 1, 4, 1, 1, path, + 0xF0F0F0, + 0xFFFFFF, - 0x000000 + 0x000000, + + nil, + 0x3C3C3C, + + 0xE1E1E1, + 0x3C3C3C, + + 0xCC2440, + 0xFFFFFF ) ) iconField.launchers.directory = function(icon) - addpath(icon.path) + addPath(icon.path) updateFileListAndDraw() end iconField.launchers.showPackageContent = function(icon) - addpath(icon.path) + addPath(icon.path) updateFileListAndDraw() end iconField.launchers.showContainingFolder = function(icon) - addpath(filesystem.path(system.readShortcut(icon.path))) + addPath(filesystem.path(system.readShortcut(icon.path))) updateFileListAndDraw() end iconField.eventHandler = function(workspace, self, e1, e2, e3, e4, e5) if e1 == "scroll" then - if config.gridMode then - local iconsCount = #iconField.children + setVerticalScroll(getVerticalScroll() + (config.gridMode and e5 * 2 or e5)) - if iconsCount < 2 then - return - end - - local rows = math.ceil((iconsCount - 1) / iconField.iconCount.horizontal) - local minimumOffset = (rows - 1) * (userSettings.iconHeight + userSettings.iconVerticalSpace) - userSettings.iconVerticalSpace - - iconField.yOffset = math.max(-minimumOffset + 1, math.min(iconField.yOffsetInitial, iconField.yOffset + e5 * 2)) - - -- Moving icons upper or lower - local delta, child = iconField.yOffset - iconField.children[2].localY - - for i = 1, iconsCount do - child = iconField.children[i] - - if child ~= iconField.backgroundObject then - child.localY = child.localY + delta - end - end - - workspace:draw() - else - GUI.tableEventHandler(workspace, self, e1, e2, e3, e4, e5) - end + workspace:draw() elseif e1 == "system" or e1 == "Finder" then if e2 == "updateFileList" then updateFileListAndDraw() + elseif e2 == "updateFavourites" then if e3 then table.insert(config.favourites, e3) @@ -511,7 +535,7 @@ local function updateIconField() local function addNode(text, path) statusContainer:addChild(GUI.adaptiveButton(x, 1, 0, 0, nil, 0xC3C3C3, nil, 0xFFFFFF, text)).onTouch = function() - addpath(path) + addPath(path) updateFileListAndDraw() end @@ -550,7 +574,7 @@ gotoButton.onTouch = function() input.text = ("/" .. input.text .. "/"):gsub("/+", "/") if filesystem.exists(input.text) and filesystem.isDirectory(input.text) then - addpath(input.text) + addPath(input.text) iconField:updateFileList() end @@ -617,9 +641,9 @@ modeList.selectedItem = config.gridMode == nil and 2 or (config.gridMode and 1 o updateIconField() if (options.o or options.open) and args[1] and filesystem.isDirectory(args[1]) then - addpath(args[1]) + addPath(args[1]) else - addpath("/") + addPath("/") end updateSidebar() diff --git a/Applications/Picture Edit.app/Tools/1.lua b/Applications/Picture Edit.app/Tools/1.lua index 196c4fc1..5083c4be 100644 --- a/Applications/Picture Edit.app/Tools/1.lua +++ b/Applications/Picture Edit.app/Tools/1.lua @@ -192,8 +192,8 @@ selector.draw = function() screen.drawText(selector.x + selector.width - 1, selector.y, 0x0, "┓") screen.drawText(selector.x, selector.y + selector.height - 1, 0x0, "┗") - screen.drawText(selector.x, selector.y, 0x66FF80, "⬤") - screen.drawText(selector.x + selector.width - 1, selector.y + selector.height - 1, 0x66FF80, "⬤") + screen.drawText(selector.x, selector.y, 0x66FF80, "●") + screen.drawText(selector.x + selector.width - 1, selector.y + selector.height - 1, 0x66FF80, "●") end ------------------------------------------------------ diff --git a/Applications/Pioneer.app/Images/Background.pic b/Applications/Pioneer.app/Images/Background.pic index 03fec8e50e24e7f107c9753ec70690a95b6767ab..03ad7a91289796ce6fdeedb543b90c1201e1b32e 100644 GIT binary patch delta 6935 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 delta 7268 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 diff --git a/Applications/Pioneer.app/Main.lua b/Applications/Pioneer.app/Main.lua index bba22ab8..74356cb7 100644 --- a/Applications/Pioneer.app/Main.lua +++ b/Applications/Pioneer.app/Main.lua @@ -7,6 +7,8 @@ local image = require("Image") local paths = require("Paths") local system = require("System") local text = require("Text") +local internet = require("Internet") +local event = require("Event") -------------------------------------------------------------------------------- @@ -37,7 +39,7 @@ local tape local tapeWritingProgress local function updateCurrentTapeSpeed() - tape.proxy.setSpeed(speedMin + tape.speed * (speedMax - speedMin)) + component.invoke(tape.address, "setSpeed", speedMin + tape.speed * (speedMax - speedMin)) end local function updateCurrentTape() @@ -65,324 +67,16 @@ local function updateTapes() for address in component.list("tape_drive") do table.insert(tapes, { - proxy = component.proxy(address), + address = address, + size = component.invoke(address, "getSize"), speed = 0.5, - cues = {} + cues = {}, }) end updateCurrentTape() end - --------------------------------- Window ------------------------------------------------ - -local backgroundImage = loadImage("Background") - -local workspace, window, menu = system.addWindow(GUI.window(1, 1, 78, 49)) - -window.drawShadow = false - - - --------------------------------- Jog ------------------------------------------------ - -local jogImages = {} - -for i = 1, 12 do - jogImages[i] = loadImage("Jog" .. i) -end - - -local function getIsPlaying() - return tape.proxy.getState() == "PLAYING" -end - --------------------------------- Background ------------------------------------------------ - -local windowBackground = window:addChild(GUI.object(1, 1, window.width, window.height)) - -local currentJogIndex = 1 -local displayWidth, displayHeight = 33, 9 - -local function displayDrawProgressBar(x, y, width, progress) - local progressActiveWidth = math.floor(progress * width) - - screen.drawText(x, y, 0xE1E1E1, string.rep("━", progressActiveWidth)) - screen.drawText(x + progressActiveWidth, y, 0x4B4B4B, string.rep("━", width - progressActiveWidth)) -end - -windowBackground.draw = function(windowBackground) - -- Background - screen.drawImage(windowBackground.x, windowBackground.y, backgroundImage) - - - -- Speed slider indicator - screen.drawText(windowBackground.x + 68, windowBackground.y + 39, powerButton.pressed and 0xFFDB40 or 0x332400, "⠆") - - -- Ignoring if power is off - if not powerButton.pressed then - return - end - - -- Jog - screen.drawImage(windowBackground.x + 33, windowBackground.y + 29, jogImages[currentJogIndex]) - - -- Display - local displayX, displayY = windowBackground.x + 22, windowBackground.y + 3 - local displayUpperText - - if tapeWritingProgress then - displayUpperText = "Writing in progress" - - local progressWidth = displayWidth - 4 - - displayDrawProgressBar( - math.floor(displayX + displayWidth / 2 - progressWidth / 2), - math.floor(displayY + displayHeight / 2), - progressWidth, - tapeWritingProgress - ) - else - -- UpperText - displayUpperText = tape.proxy.getLabel() - - if not displayUpperText or #displayUpperText == 0 then - displayUpperText = "Untitled tape" - end - - -- BPM - local bpmText = tostring(math.floor(bpmMin + speedSlider.value * (bpmMax - bpmMin))) .. " bpm" - local bpmWidth = #bpmText + 4 - - local bpmX = displayX + displayWidth - 2 - bpmWidth - local bpmY = displayY + displayHeight - 5 - - screen.drawFrame(bpmX, bpmY, bpmWidth, 3, 0xE1E1E1) - screen.drawText(bpmX + 2, bpmY + 1, 0xE1E1E1, bpmText) - - -- Lower track - local progressWidth = displayWidth - 4 - local tapeSize = tape.proxy.getSize() - - displayDrawProgressBar( - math.floor(displayX + displayWidth / 2 - progressWidth / 2), - displayY + displayHeight - 2, - progressWidth, - tapeSize == 0 and 0 or tape.proxy.getPosition() / tapeSize - ) - end - - -- UpperText - displayUpperText = text.limit(displayUpperText, displayWidth - 2) - screen.drawText(math.floor(displayX + displayWidth / 2 - #displayUpperText / 2), displayY + 1, 0xE1E1E1, displayUpperText) -end - --------------------------------- Power button ------------------------------------------------ - -powerButton = window:addChild(GUI.object(75, 2, 4, 2)) - -powerButton.pressed = false - -powerButton.draw = function() - screen.drawText(powerButton.x, powerButton.y, 0x1E1E1E, powerButton.pressed and "⣠⣤⣄" or "⣸⣿⣇") -end - -powerButton.eventHandler = function(workspace, powerButton, e1) - if e1 == "touch" then - powerButton.pressed = not powerButton.pressed - workspace:draw() - - computer.beep(20, 0.01) - end -end - --------------------------------- ImageButton ------------------------------------------------ - -local imageButtonBlink = false -local imageButtonBlinkUptime = 0 -local imageButtonBlinkInterval = 0.5 - -local function imageButtonDraw(button) - screen.drawImage(button.x, button.y, (powerButton.pressed and (not button.blinking or imageButtonBlink)) and button.imageOn or button.imageOff) -end - -local function newImageButton(x, y, width, height, name) - local button = GUI.object(x, y, width, height) - - button.imageOn = loadImage(name .. "On") - button.imageOff = loadImage(name .. "Off") - - button.draw = imageButtonDraw - - return button -end - - --------------------------------- Speed slider ------------------------------------------------ - -local speedSliderImage = loadImage("SpeedSlider") - -speedSlider = window:addChild(GUI.object(71, 33, 5, 14)) - -speedSlider.draw = function(speedSlider) - -- screen.drawRectangle(speedSlider.x, speedSlider.y, speedSlider.width, speedSlider.height, 0xFF0000, 0x0, " ") - - local x = speedSlider.x - local y = speedSlider.y + math.floor((1 - speedSlider.value) * (speedSlider.height - image.getHeight(speedSliderImage) / 2)) - - screen.drawImage(x, y, speedSliderImage) -end - -speedSlider.eventHandler = function(workspace, speedSlider, e1, e2, e3, e4) - if e1 == "touch" or e1 == "drag" then - speedSlider.value = 1 - ((e4 - speedSlider.y) / speedSlider.height) - tape.speed = speedSlider.value - - updateCurrentTapeSpeed() - - workspace:draw() - end -end - --------------------------------- UpperButtons ------------------------------------------------ - -local function upperButtonDraw(button) - local bg, fg = button.animationCurrentBackground, powerButton.pressed and button.animationCurrentText or 0x0 - - -- Background - screen.drawRectangle(button.x + 1, button.y + 1, button.width - 2, button.height - 2, bg, fg, " ") - - -- Upper - screen.drawText(button.x, button.y, fg, "⢀" .. string.rep("⣀", button.width - 2) .. "⡀") - - -- Left - screen.drawText(button.x, button.y + 1, fg, "⢸") - - -- Middle - screen.drawText(math.floor(button.x + button.width / 2 - #button.text / 2), button.y + 1, fg, button.text) - - -- Right - screen.drawText(button.x + button.width - 1, button.y + 1, fg, "⡇") - - -- Lower - screen.drawText(button.x, button.y + button.height - 1, fg, "⠈" .. string.rep("⠉", button.width - 2) .. "⠁") - -end - -local function upperButtonEventHandler(workspace, button, e1, e2, e3, e4, e5) - if e1 == "touch" and powerButton.pressed then - button:press() - end -end - -local function newUpperButton(x, y, width, text) - local button = GUI.button(x, y, width, 3, 0x2D2D2D, 0xFFB600, 0x2D2D2D, 0x996D00, text) - - button.pressed = false - button.draw = upperButtonDraw - button.eventHandler = upperButtonEventHandler - - return button -end - --------------------------------- Write upper button ------------------------------------------------ - -local writeUpperButton = window:addChild(newUpperButton(23, 1, 9, "Write")) - -writeUpperButton.onTouch = function() - local filesystemDialog = GUI.addFilesystemDialog(workspace, true, 50, math.floor(window.height * 0.8), "Confirm", "Cancel", "File name", "/") - - filesystemDialog:setMode(GUI.IO_MODE_OPEN, GUI.IO_MODE_FILE) - filesystemDialog:addExtensionFilter(".dfpwm") - filesystemDialog:expandPath(paths.user.desktop) - filesystemDialog:show() - - filesystemDialog.onSubmit = function(path) - local tapeSize = tape.proxy.getSize() - local tapeSpaceFree = tapeSize - tape.proxy.getPosition() - local fileSize = filesystem.size(path) - - if fileSize > tapeSpaceFree then - GUI.alert("Not enough space on tape") - return - end - - local file = filesystem.open(path, "rb") - - tape.proxy.stop() - - local bytesWritten, chunk = 0 - while true do - chunk = file:read(8192) - - if not chunk then - break - end - - if not tape.proxy.isReady() then - GUI.alert("Tape was removed during writing") - break - end - - tape.proxy.write(chunk) - - bytesWritten = bytesWritten + #chunk - tapeWritingProgress = bytesWritten / fileSize - workspace:draw() - end - - file:close() - tape.proxy.seek(-tape.proxy.getSize()) - tapeWritingProgress = nil - end -end - --------------------------------- Label upper button ------------------------------------------------ - -local labelUpperButton = window:addChild(newUpperButton(33, 1, 9, "Label")) - -labelUpperButton.onTouch = function() - local container = GUI.addBackgroundContainer(workspace, true, true, title) - - local input = container.layout:addChild(GUI.input(1, 1, 36, 3, 0xE1E1E1, 0x696969, 0x969696, 0xE1E1E1, 0x2D2D2D, tape.proxy.getLabel() or "", "New label", false)) - - input.onInputFinished = function() - tape.proxy.setLabel(input.text) - workspace:draw() - end - - container.panel.onTouch = function() - container:remove() - workspace:draw() - end - - workspace:draw() - - return container -end - --------------------------------- Needle search ------------------------------------------------ - -local needleSearch = window:addChild(GUI.object(25, 15, 29, 2)) - -needleSearch.draw = function() - -- screen.drawRectangle(needleSearch.x, needleSearch.y, needleSearch.width, needleSearch.height, 0xFF0000, 0x0, " ") - - if powerButton.pressed then - screen.drawText(needleSearch.x, needleSearch.y, 0xE1E1E1, "▲ ╷ ╷ ╷ ╷ ╷ ╷ ╷ ╷ ╷ ╷ ╷ ╷ ╷ ▲") - end -end - -needleSearch.eventHandler = function(workspace, needleSearch, e1, e2, e3, e4) - if e1 == "touch" and powerButton.pressed and tape then - local position = tape.proxy.getPosition() - local newPosition = math.floor((e3 - needleSearch.x) / needleSearch.width * tape.proxy.getSize()) - - tape.proxy.seek(newPosition - position) - end -end - -------------------------------- Round mini button ------------------------------------------------ local function roundMiniButtonDraw(button) @@ -439,6 +133,18 @@ local function roundTinyButtonDraw(button) -- Lower screen.drawText(button.x, button.y + 1, bg, "⠈⠛⠛⠁") + + -- -- Left + -- screen.drawText(button.x, button.y, bg, "⣾") + + -- -- Middle + -- screen.set(button.x + 1, button.y, bg, fg, "⠄") + + -- -- Right + -- screen.drawText(button.x + 2, button.y, bg, "⡆") + + -- -- Lower + -- screen.drawText(button.x, button.y + 1, bg, "⠈⠉") end local function newRoundTinyButton(x, y, ...) @@ -450,6 +156,391 @@ local function newRoundTinyButton(x, y, ...) return button end +-------------------------------- UpperButtons ------------------------------------------------ + +local function upperButtonDraw(button) + local bg, fg = button.animationCurrentBackground, powerButton.pressed and button.animationCurrentText or 0x0 + + -- Background + screen.drawRectangle(button.x + 1, button.y + 1, button.width - 2, button.height - 2, bg, fg, " ") + + -- Upper + screen.drawText(button.x, button.y, fg, "⢀" .. string.rep("⣀", button.width - 2) .. "⡀") + + -- Left + screen.drawText(button.x, button.y + 1, fg, "⢸") + + -- Middle + screen.drawText(math.floor(button.x + button.width / 2 - unicode.len(button.text) / 2), button.y + 1, fg, button.text) + + -- Right + screen.drawText(button.x + button.width - 1, button.y + 1, fg, "⡇") + + -- Lower + screen.drawText(button.x, button.y + button.height - 1, fg, "⠈" .. string.rep("⠉", button.width - 2) .. "⠁") + +end + +local function upperButtonEventHandler(workspace, button, e1, e2, e3, e4, e5) + if e1 == "touch" and powerButton.pressed then + button:press() + end +end + +local function newUpperButton(x, y, width, ...) + local button = GUI.button(x, y, width, 3, ...) + + button.pressed = false + button.draw = upperButtonDraw + button.eventHandler = upperButtonEventHandler + + return button +end + +-------------------------------- Round mini button ------------------------------------------------ + +local function hotCueButtonDraw(button) + local bg, fg = button.animationCurrentBackground, powerButton.pressed and button.animationCurrentText or 0x2D2D2D + + -- Upper + screen.drawText(button.x, button.y, bg, "⢀" .. string.rep("⣀", button.width - 2) .. "⡀") + + -- Left + screen.drawText(button.x, button.y + 1, bg, "⢸") + + -- Middle + screen.set(button.x + 1, button.y + 1, 0x2D2D2D, 0x5A5A5A, "⣤") + screen.set(button.x + 2, button.y + 1, bg, 0x787878, "⠤") + + screen.set(button.x + 3, button.y + 1, bg, fg, button.text) + + screen.set(button.x + 4, button.y + 1, bg, 0x787878, "⠒") + screen.set(button.x + 5, button.y + 1, 0x2D2D2D, 0x5A5A5A, "⠛") + + -- Right + screen.drawText(button.x + button.width - 1, button.y + 1, bg, "⡇") + + -- Lower + screen.drawText(button.x, button.y + button.height - 1, bg, "⠈" .. string.rep("⠉", button.width - 2) .. "⠁") + +end + +local function hotCueButtonEventHandler(workspace, button, e1, e2, e3, e4, e5) + if e1 == "touch" then + button:press() + end +end + +local function newHotCueButton(x, y, defaultForeground, pressedForeground, text) + local button = GUI.button(x, y, 7, 3, 0x1E1E1E, defaultForeground, 0x0, pressedForeground, text) + + button.draw = hotCueButtonDraw + button.eventHandler = hotCueButtonEventHandler + + return button +end + + +-------------------------------- Window ------------------------------------------------ + +local backgroundImage = loadImage("Background") + +local workspace, window, menu = system.addWindow(GUI.window(1, 1, 78, 49)) + +window.drawShadow = false + + + +-------------------------------- Jog ------------------------------------------------ + +local jogImages = {} + +for i = 1, 12 do + jogImages[i] = loadImage("Jog" .. i) +end + + +local function getIsPlaying() + return component.invoke(tape.address, "getState") == "PLAYING" +end + +-------------------------------- Background ------------------------------------------------ + +local windowBackground = window:addChild(GUI.object(1, 1, window.width, window.height)) + +local currentJogIndex = 1 +local displayWidth, displayHeight = 33, 9 + +local function displayDrawProgressBar(x, y, width, progress) + local progressActiveWidth = math.floor(progress * width) + + screen.drawText(x, y, 0xE1E1E1, string.rep("━", progressActiveWidth)) + screen.drawText(x + progressActiveWidth, y, 0x4B4B4B, string.rep("━", width - progressActiveWidth)) +end + +windowBackground.draw = function(windowBackground) + -- Background + screen.drawImage(windowBackground.x, windowBackground.y, backgroundImage) + + -- Ignoring if power is off + if not powerButton.pressed then + return + end + + -- Power indicator + screen.drawText(windowBackground.x + 73, windowBackground.y + 3, 0xFF0000, "●") + + -- Speed slider indicator + screen.drawText(windowBackground.x + 68, windowBackground.y + 39, 0xFFDB40, "⠆") + + -- Jog + screen.drawImage(windowBackground.x + 33, windowBackground.y + 29, jogImages[currentJogIndex]) + + -- Display + local displayX, displayY = windowBackground.x + 22, windowBackground.y + 3 + local displayUpperText + + if tapeWritingProgress then + displayUpperText = "Writing in progress" + + local progressWidth = displayWidth - 4 + + displayDrawProgressBar( + math.floor(displayX + displayWidth / 2 - progressWidth / 2), + math.floor(displayY + displayHeight / 2), + progressWidth, + tapeWritingProgress + ) + else + -- UpperText + displayUpperText = component.invoke(tape.address, "getLabel") + + if not displayUpperText or #displayUpperText == 0 then + displayUpperText = "Untitled tape" + end + + -- BPM + local bpmText = tostring(math.floor(bpmMin + speedSlider.value * (bpmMax - bpmMin))) .. " bpm" + local bpmWidth = #bpmText + 4 + + local bpmX = displayX + displayWidth - 2 - bpmWidth + local bpmY = displayY + displayHeight - 5 + + screen.drawFrame(bpmX, bpmY, bpmWidth, 3, 0xE1E1E1) + screen.drawText(bpmX + 2, bpmY + 1, 0xE1E1E1, bpmText) + + -- Lower track + local progressWidth = displayWidth - 4 + + displayDrawProgressBar( + math.floor(displayX + displayWidth / 2 - progressWidth / 2), + displayY + displayHeight - 2, + progressWidth, + tape.size == 0 and 0 or component.invoke(tape.address, "getPosition") / tape.size + ) + end + + -- UpperText + displayUpperText = text.limit(displayUpperText, displayWidth - 2) + screen.drawText(math.floor(displayX + displayWidth / 2 - #displayUpperText / 2), displayY + 1, 0xE1E1E1, displayUpperText) +end + +-------------------------------- Power button ------------------------------------------------ + +powerButton = window:addChild(GUI.object(75, 2, 4, 2)) + +powerButton.pressed = false + +powerButton.draw = function() + screen.drawText(powerButton.x, powerButton.y, 0x1E1E1E, powerButton.pressed and "⣠⣤⣄" or "⣸⣿⣇") +end + +powerButton.eventHandler = function(workspace, powerButton, e1) + if e1 == "touch" then + powerButton.pressed = not powerButton.pressed + + -- Stopping playback + if powerButton.pressed then + currentJogIndex = 1 + else + for i = 1, #tapes do + component.invoke(tapes[i].address, "stop") + end + end + + workspace:draw() + + computer.beep(20, 0.01) + end +end + +-------------------------------- ImageButton ------------------------------------------------ + +local imageButtonBlink = false +local imageButtonBlinkUptime = 0 +local imageButtonBlinkInterval = 0.5 + +local function imageButtonDraw(button) + screen.drawImage(button.x, button.y, (powerButton.pressed and (not button.blinking or imageButtonBlink)) and button.imageOn or button.imageOff) +end + +local function newImageButton(x, y, width, height, name) + local button = GUI.object(x, y, width, height) + + button.imageOn = loadImage(name .. "On") + button.imageOff = loadImage(name .. "Off") + + button.draw = imageButtonDraw + + return button +end + + +-------------------------------- Speed slider ------------------------------------------------ + +local speedSliderImage = loadImage("SpeedSlider") + +speedSlider = window:addChild(GUI.object(71, 33, 5, 14)) + +speedSlider.draw = function(speedSlider) + -- screen.drawRectangle(speedSlider.x, speedSlider.y, speedSlider.width, speedSlider.height, 0xFF0000, 0x0, " ") + + local x = speedSlider.x + local y = speedSlider.y + math.floor((1 - speedSlider.value) * (speedSlider.height - image.getHeight(speedSliderImage) / 2)) + + screen.drawImage(x, y, speedSliderImage) +end + +speedSlider.eventHandler = function(workspace, speedSlider, e1, e2, e3, e4) + if e1 == "touch" or e1 == "drag" then + speedSlider.value = 1 - ((e4 - speedSlider.y) / speedSlider.height) + tape.speed = speedSlider.value + + updateCurrentTapeSpeed() + + workspace:draw() + end +end + +-------------------------------- File/url/label upper buttons ------------------------------------------------ + +local _ = window:addChild(newUpperButton(14, 1, 7, 0x1E1E1E, 0xF0F0F0, 0x0F0F0F, 0xA5A5A5, "Help")) +local urlUpperButton = window:addChild(newUpperButton(14, 4, 7, 0x1E1E1E, 0x3349FF, 0x0F0F0F, 0x002480, "Url")) +local fileUpperButton = window:addChild(newUpperButton(14, 7, 7, 0x1E1E1E, 0xFFDB40, 0x0F0F0F, 0x996D00, "File")) + +local _ = window:addChild(newRoundTinyButton(14, 12, 0x0F0F0F, 0xFF0000, 0x0F0F0F, 0xFF0000, "⢠⡄")) +local _ = window:addChild(newRoundTinyButton(18, 12, 0x0F0F0F, 0x2D2D2D, 0x0F0F0F, 0x2D2D2D, "⢠⡄")) + +local labelUpperButton = window:addChild(newUpperButton(23, 1, 9, 0x1E1E1E, 0xFFDB40, 0x0F0F0F, 0x996D00, "Label")) +local _ = window:addChild(newUpperButton(33, 1, 9, 0x1E1E1E, 0xFFDB40, 0x0F0F0F, 0x996D00, " ")) +local _ = window:addChild(newUpperButton(43, 1, 9, 0x1E1E1E, 0xFFDB40, 0x0F0F0F, 0x996D00, " ")) + +fileUpperButton.onTouch = function() + local filesystemDialog = GUI.addFilesystemDialog(workspace, true, 50, math.floor(window.height * 0.8), "Confirm", "Cancel", "File name", "/") + + filesystemDialog:setMode(GUI.IO_MODE_OPEN, GUI.IO_MODE_FILE) + filesystemDialog:addExtensionFilter(".dfpwm") + filesystemDialog:expandPath(paths.user.desktop) + filesystemDialog:show() + + filesystemDialog.onSubmit = function(path) + local tapeSpaceFree = tape.size - component.invoke(tape.address, "getPosition") + local fileSize = filesystem.size(path) + + if fileSize > tapeSpaceFree then + GUI.alert("Not enough space on tape") + return + end + + local file = filesystem.open(path, "rb") + + component.invoke(tape.address, "stop") + + local bytesWritten, chunk = 0 + while true do + chunk = file:read(8192) + + if not chunk then + break + end + + if not component.invoke(tape.address, "isReady") then + GUI.alert("Tape was removed during writing") + break + end + + component.invoke(tape.address, "write", chunk) + + bytesWritten = bytesWritten + #chunk + tapeWritingProgress = bytesWritten / fileSize + workspace:draw() + end + + file:close() + component.invoke(tape.address, "seek", -tape.size) + tapeWritingProgress = nil + end +end + +urlUpperButton.onTouch = function() + local container = GUI.addBackgroundContainer(workspace, true, true, title) + + local input = container.layout:addChild(GUI.input(1, 1, 36, 3, 0xE1E1E1, 0x696969, 0x969696, 0xE1E1E1, 0x2D2D2D, "", "Url", false)) + + input.onInputFinished = function() + + + workspace:draw() + end + + container.panel.onTouch = function() + container:remove() + workspace:draw() + end + + workspace:draw() + + return container +end + +labelUpperButton.onTouch = function() + local container = GUI.addBackgroundContainer(workspace, true, true, title) + + local input = container.layout:addChild(GUI.input(1, 1, 36, 3, 0xE1E1E1, 0x696969, 0x969696, 0xE1E1E1, 0x2D2D2D, component.invoke(tape.address, "getLabel") or "", "New label", false)) + + input.onInputFinished = function() + component.invoke(tape.address, "setLabel", input.text) + workspace:draw() + end + + container.panel.onTouch = function() + container:remove() + workspace:draw() + end + + workspace:draw() + + return container +end + +-------------------------------- Needle search ------------------------------------------------ + +local needleSearch = window:addChild(GUI.object(25, 15, 29, 2)) + +needleSearch.draw = function() + -- screen.drawRectangle(needleSearch.x, needleSearch.y, needleSearch.width, needleSearch.height, 0xFF0000, 0x0, " ") + + screen.drawText(needleSearch.x, needleSearch.y, powerButton.pressed and 0xE1E1E1 or 0x0, "▲ ╷ ╷ ╷ ╷ ╷ ╷ ╷ ╷ ╷ ╷ ╷ ╷ ╷ ▲") +end + +needleSearch.eventHandler = function(workspace, needleSearch, e1, e2, e3, e4) + if e1 == "touch" and powerButton.pressed and tape then + local position = component.invoke(tape.address, "getPosition") + local newPosition = math.floor((e3 - needleSearch.x) / needleSearch.width * tape.size) + + component.invoke(tape.address, "seek", newPosition - position) + end +end -------------------------------- Pref/next tape button ------------------------------------------------ @@ -477,6 +568,106 @@ nextSearchButton.onTouch = function() end +-------------------------------- Hot cue buttons ------------------------------------------------ + +local hotCueButtonA = window:addChild(newHotCueButton(3, 13, 0x66FF40, 0x336D00, "A")) +local hotCueButtonB = window:addChild(newHotCueButton(3, 16, 0xFFB600, 0x664900, "B")) +local hotCueButtonB = window:addChild(newHotCueButton(3, 19, 0xFF2440, 0x660000, "C")) +local hotCueSaveLoad = window:addChild(newHotCueButton(3, 23, 0x0F0F0F, 0x000000, "⠰⠆")) + +hotCueSaveLoad.draw = function(button) + local bg, fg = button.animationCurrentBackground, button.animationCurrentText + + -- Upper + screen.drawText(button.x, button.y, bg, "⢀" .. string.rep("⣀", button.width - 2) .. "⡀") + + -- Left + screen.drawText(button.x, button.y + 1, bg, "⢸") + + -- Middle + screen.set(button.x + 1, button.y + 1, 0x2D2D2D, fg, " ") + screen.set(button.x + 2, button.y + 1, 0x2D2D2D, fg, " ") + screen.set(button.x + 3, button.y + 1, 0x2D2D2D, fg, "⠶") + screen.set(button.x + 4, button.y + 1, 0x2D2D2D, fg, " ") + screen.set(button.x + 5, button.y + 1, 0x2D2D2D, fg, " ") + + -- Right + screen.drawText(button.x + button.width - 1, button.y + 1, bg, "⡇") + + -- Lower + screen.drawText(button.x, button.y + button.height - 1, bg, "⠈" .. string.rep("⠉", button.width - 2) .. "⠁") +end + + +hotCueButtonA.onTouch = function() + +end + +-------------------------------- Loop buttons ------------------------------------------------ + +local function loopButtonDraw(button) + local border, color1, color2, color3, color4 + + if powerButton.pressed then + if button.pressed then + border, color1, color2, color3, color4 = 0x332400, 0x996D00, 0x996D00, 0x996D00, 0x996D00 + else + border, color1, color2, color3, color4 = 0x332400, 0xFFDB80, 0xFFDB40, 0xFFB680, 0xFFB640 + end + else + border, color1, color2, color3, color4 = 0x0F0F0F, 0x332400, 0x332400, 0x332400, 0x332400 + end + + -- 1 + screen.drawText(button.x, button.y, border, "⢰") + screen.set(button.x + 1, button.y, color1, border, "⠉") + screen.set(button.x + 2, button.y, color2, border, "⠉") + screen.set(button.x + 3, button.y, color3, border, "⠉") + screen.drawText(button.x + 4, button.y, border, "⡆") + + -- 2 + screen.drawText(button.x, button.y + 1, border, "⠸") + screen.set(button.x + 1, button.y + 1, color4, border, "⣀") + screen.set(button.x + 2, button.y + 1, color4, border, "⣀") + screen.set(button.x + 3, button.y + 1, color3, border, "⣀") + screen.drawText(button.x + 4, button.y + 1, border, "⠇") +end + +local function loopButtonEventHandler(workspace, button, e1, e2, e3, e4, e5) + if e1 == "touch" then + button.pressed = true + workspace:draw() + + event.sleep(0.2) + + button.pressed = false + workspace:draw() + + if button.onTouch then + button.onTouch() + end + end +end + +local function newLoopButton(x, y) + local button = GUI.object(x, y, 5, 2) + + button.pressed = false + button.draw = loopButtonDraw + button.eventHandler = loopButtonEventHandler + + return button +end + + +local loopButtonIn = window:addChild(newLoopButton(13, 18)) +local loopButtonOut = window:addChild(newLoopButton(19, 18)) + +local reloopButton = window:addChild(newRoundTinyButton(26, 18, 0x2D2D2D, 0xFFB640, 0x1E1E1E, 0x996D00, "⢠⡄")) + +loopButtonIn.onTouch = function() + +end -------------------------------- Cue button ------------------------------------------------ @@ -498,11 +689,7 @@ playButton.eventHandler = function(workspace, playButton, e1) if e1 == "touch" and powerButton.pressed then playButton.blinking = not playButton.blinking - if playButton.blinking then - tape.proxy.stop() - else - tape.proxy.play() - end + component.invoke(tape.address, playButton.blinking and "stop" or "play") workspace:draw() end @@ -517,7 +704,7 @@ local beatSyncMasterButton = window:addChild(newRoundMiniButton(74, 24, 0xB4B4B4 local tempoButton = window:addChild(newRoundTinyButton(72, 28, 0x0F0F0F, 0x2D2D2D, 0x0, 0xFF2440, " ")) -local masterTempoButton = window:addChild(newRoundTinyButton(72, 31, 0x0F0F0F, 0x2D2D2D, 0x0F0F0F, 0xFF2440, "⢠⡄")) +local masterTempoButton = window:addChild(newRoundTinyButton(72, 31, 0x0F0F0F, 0x2D2D2D, 0x0F0F0F, 0xFF0000, "⢠⡄")) masterTempoButton.switchMode = true masterTempoButton:press() @@ -542,6 +729,12 @@ window.eventHandler = function(workspace, window, e1, ...) local uptime = computer.uptime() + -- Cheching if play button state was changed + if isPlaying == playButton.blinking then + playButton.blinking = not playButton.blinking + shouldDraw = true + end + if isPlaying then if uptime > jogIncrementUptime then -- Rotating jog @@ -565,14 +758,6 @@ window.eventHandler = function(workspace, window, e1, ...) shouldDraw = true end - if not e1 then - -- Cheching if play button state was changed - if isPlaying == playButton.blinking then - playButton.blinking = not playButton.blinking - shouldDraw = true - end - end - if shouldDraw then workspace:draw() end diff --git a/Libraries/GUI.lua b/Libraries/GUI.lua index f2d9bd8f..08395c94 100755 --- a/Libraries/GUI.lua +++ b/Libraries/GUI.lua @@ -611,11 +611,13 @@ local function buttonPlayAnimation(button, onFinish) if button.colors.default.background and button.colors.pressed.background then button.animationCurrentBackground = color.transition(button.colors.pressed.background, button.colors.default.background, animation.position) end + button.animationCurrentText = color.transition(button.colors.pressed.text, button.colors.default.text, animation.position) else if button.colors.default.background and button.colors.pressed.background then button.animationCurrentBackground = color.transition(button.colors.default.background, button.colors.pressed.background, animation.position) end + button.animationCurrentText = color.transition(button.colors.default.text, button.colors.pressed.text, animation.position) end end, @@ -4728,8 +4730,8 @@ end --------------------------------------------------------------------------------------------------- local function tableHeaderDraw(self) - screen.drawRectangle(self.x, self.y, self.width, self.height, self.parent.colors.headerBackground, self.parent.colors.headerText, " ") - screen.drawText(self.x + 1, self.y, self.parent.colors.headerText, self.text) + screen.drawRectangle(self.x, self.y, self.width, self.height, self.parent.colors.headerBackground, self.parent.colors.headerForeground, " ") + screen.drawText(self.x + 1, self.y, self.parent.colors.headerForeground, self.text) end local function tableAddColumn(self, headerText, sizePolicy, size) @@ -4810,28 +4812,34 @@ end function GUI.tableCellDraw(self) local background, foreground + if self.selected then - background, foreground = self.colors.selectionBackground, self.colors.selectionText + background, foreground = + self.colors.selectionBackground or self.parent.colors.itemSelectionBackground, + self.colors.selectionForeground or self.parent.colors.itemSelectionForeground + elseif self.alternative then - background, foreground = self.colors.alternativeBackground, self.colors.alternativeText + background, foreground = + self.colors.alternativeBackground or self.parent.colors.itemAlternativeBackground, + self.colors.alternativeForeground or self.parent.colors.itemAlternativeForeground + else - background, foreground = self.colors.defaultBackground, self.colors.defaultText + background, foreground = + self.colors.defaultBackground or self.parent.colors.itemDefaultBackground, + self.colors.defaultForeground or self.parent.colors.itemDefaultForeground end if background then - screen.drawRectangle(self.x, self.y, self.width, self.height, - background, - foreground, - " ") + screen.drawRectangle(self.x, self.y, self.width, self.height, background, foreground or 0x0, " ") end - return foreground + return foreground or 0x0 end -function GUI.tableCell(colors) +function GUI.tableCell() local cell = GUI.object(1, 1, 1, 1) - cell.colors = colors + cell.colors = {} cell.draw = GUI.tableCellDraw cell.eventHandler = GUI.tableCellEventHandler @@ -4839,11 +4847,11 @@ function GUI.tableCell(colors) end local function tableTextCellDraw(self) - screen.drawText(self.x + 1, self.y, GUI.tableCellDraw(self), self.text) + screen.drawText(self.x + 1, self.y, GUI.tableCellDraw(self) or 0x0, self.text) end -function GUI.tableTextCell(colors, text) - local cell = GUI.tableCell(colors) +function GUI.tableTextCell(text) + local cell = GUI.tableCell() cell.text = text cell.draw = tableTextCellDraw @@ -4893,7 +4901,9 @@ function GUI.tableEventHandler(workspace, self, e1, e2, e3, e4, e5, ...) end if not itemTouched then - self.onBackgroundTouch(workspace, self, e1, e2, e3, e4, e5, ...) + if self.onBackgroundTouch then + self.onBackgroundTouch(workspace, self, e1, e2, e3, e4, e5, ...) + end end elseif e1 == "scroll" then @@ -4902,13 +4912,43 @@ function GUI.tableEventHandler(workspace, self, e1, e2, e3, e4, e5, ...) end end -function GUI.table(x, y, width, height, itemHeight, backgroundColor, headerBackgroundColor, headerTextColor) +function GUI.table( + x, + y, + width, + height, + itemHeight, + + background, + + headerBackground, + headerForeground, + + itemDefaultBackground, + itemDefaultForeground, + + itemAlternativeBackground, + itemAlternativeForeground, + + itemSelectionBackground, + itemSelectionForeground +) local table = GUI.layout(x, y, width, height, 0, 2) table.colors = { - background = backgroundColor, - headerBackground = headerBackgroundColor, - headerText = headerTextColor + background = background, + + headerBackground = headerBackground, + headerForeground = headerForeground, + + itemDefaultBackground = itemDefaultBackground, + itemDefaultForeground = itemDefaultForeground, + + itemAlternativeBackground = itemAlternativeBackground, + itemAlternativeForeground = itemAlternativeForeground, + + itemSelectionBackground = itemSelectionBackground, + itemSelectionForeground = itemSelectionForeground } table.itemHeight = itemHeight @@ -4928,51 +4968,6 @@ function GUI.table(x, y, width, height, itemHeight, backgroundColor, headerBackg return table end ---------------------------------------------------------------------------------------------------- - --- local workspace = GUI.workspace() - --- workspace:addChild(GUI.panel(1, 1, workspace.width, workspace.height, 0x2D2D2D)) - --- local t = workspace:addChild(GUI.table(3, 2, 80, 30, 1, --- 0xF0F0F0, --- 0xFFFFFF, --- 0x000000 --- )) - --- t:addColumn("Name", GUI.SIZE_POLICY_RELATIVE, 0.6) --- t:addColumn("Date", GUI.SIZE_POLICY_RELATIVE, 0.4) --- t:addColumn("Size", GUI.SIZE_POLICY_ABSOLUTE, 16) --- t:addColumn("Type", GUI.SIZE_POLICY_ABSOLUTE, 10) - --- local colors1 = { --- defaultBackground = nil, --- defaultText = 0x3C3C3C, --- alternativeBackground = 0xE1E1E1, --- alternativeText = 0x3C3C3C, --- selectionBackground = 0xCC2440, --- selectionText = 0xFFFFFF, --- } - --- local colors2 = {} --- for key, value in pairs(colors1) do --- colors2[key] = value --- end --- colors2.defaultText, colors2.alternativeText = 0xA5A5A5, 0xA5A5A5 - --- for i = 1, 10 do --- t:addRow( --- GUI.tableTextCell(colors1, "Ehehehe " .. i), --- GUI.tableTextCell(colors2, "12.02.2018"), --- GUI.tableTextCell(colors2, "114.23 KB"), --- GUI.tableTextCell(colors2, ".lua") --- ) --- end - --- workspace:draw() --- workspace:start() - - --------------------------------------------------------------------------------------------------- return GUI diff --git a/Libraries/System.lua b/Libraries/System.lua index 9cdbda02..3d470c23 100755 --- a/Libraries/System.lua +++ b/Libraries/System.lua @@ -1289,22 +1289,31 @@ local function listIconFieldUpdateFileList(iconField) -- Removing old rows iconField:clear() - local function cell1Draw(self) + local function firstCell(self) local foreground = GUI.tableCellDraw(self) screen.drawText(self.x, self.y, self.pizda, " ■ ") screen.drawText(self.x + 3, self.y, foreground, self.name) end - local function newCell1(path) - local icon = GUI.tableCell(iconField.cell1Colors) - - anyIconAddInfo(icon, path) - anyIconFieldAddIcon(iconField, icon) + local function newFirstCell(path) + local cell = GUI.tableCell() - icon.draw = cell1Draw + anyIconAddInfo(cell, path) + anyIconFieldAddIcon(iconField, cell) - return icon + cell.draw = firstCell + + return cell + end + + local function newOtherCell(text) + local cell = GUI.tableTextCell(text) + + cell.colors.defaultForeground = 0xA5A5A5 + cell.colors.alternativeForeground = 0xA5A5A5 + + return cell end local file @@ -1314,22 +1323,23 @@ local function listIconFieldUpdateFileList(iconField) if file then file = iconField.path .. file - local icon = newCell1(file) + local firstCell = newFirstCell(file) - -- Adding a single-pixel representation of icon - for i = 3, #icon.image, 4 do - if icon.image[i + 2] == 0 then - icon.pizda = icon.image[i] + -- Adding a single-pixel representation of firstCell + for i = 3, #firstCell.image, 4 do + if firstCell.image[i + 2] == 0 then + firstCell.pizda = firstCell.image[i] break end end - icon.pizda = icon.pizda or 0x0 + + firstCell.pizda = firstCell.pizda or 0x0 iconField:addRow( - icon, - GUI.tableTextCell(iconField.cell2Colors, os.date(userSettings.timeFormat, math.floor(filesystem.lastModified(file) / 1000 + userSettings.timeTimezone))), - GUI.tableTextCell(iconField.cell2Colors, icon.isDirectory and "-" or number.roundToDecimalPlaces(filesystem.size(file) / 1024, 2) .. " KB"), - GUI.tableTextCell(iconField.cell2Colors, icon.isDirectory and localization.folder or(icon.extension and icon.extension:sub(2, 2):upper() .. icon.extension:sub(3, -1) or "-")) + firstCell, + newOtherCell(os.date(userSettings.timeFormat, math.floor(filesystem.lastModified(file) / 1000 + userSettings.timeTimezone))), + newOtherCell(firstCell.isDirectory and "-" or number.roundToDecimalPlaces(filesystem.size(file) / 1024, 2) .. " KB"), + newOtherCell(firstCell.isDirectory and localization.folder or(firstCell.extension and firstCell.extension:sub(2, 2):upper() .. firstCell.extension:sub(3, -1) or "-")) ) else break @@ -1803,23 +1813,6 @@ end function system.listIconField(x, y, width, height, path, ...) local iconField = GUI.table(x, y, width, height, 1, ...) - -- First cell colors - iconField.cell1Colors = { - defaultBackground = nil, - defaultText = 0x3C3C3C, - alternativeBackground = 0xE1E1E1, - alternativeText = 0x3C3C3C, - selectionBackground = 0xCC2440, - selectionText = 0xFFFFFF, - } - - -- Other cells colors - iconField.cell2Colors = {} - for key, value in pairs(iconField.cell1Colors) do - iconField.cell2Colors[key] = value - end - iconField.cell2Colors.defaultText, iconField.cell2Colors.alternativeText = 0xA5A5A5, 0xA5A5A5 - iconField:addColumn(localization.name, GUI.SIZE_POLICY_RELATIVE, 0.6) iconField:addColumn(localization.date, GUI.SIZE_POLICY_RELATIVE, 0.4) iconField:addColumn(localization.size, GUI.SIZE_POLICY_ABSOLUTE, 16)