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 03fec8e5..03ad7a91 100644 Binary files a/Applications/Pioneer.app/Images/Background.pic and b/Applications/Pioneer.app/Images/Background.pic differ 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)