VERSION DVX 1.00
Begin Form IconEd
    Caption   = "DVX Icon Editor"
    Layout    = VBox
    AutoSize  = True
    Resizable = False
    Centered  = True

    Begin Menu mnuFile
        Caption = "&File"
        Begin Menu mnuNew
            Caption = "&New"
        End
        Begin Menu mnuOpen
            Caption = "&Open..."
        End
        Begin Menu mnuSave
            Caption = "&Save..."
        End
        Begin Menu mnuSep1
            Caption = "-"
        End
        Begin Menu mnuExit
            Caption = "E&xit"
        End
    End

    Begin Menu mnuTools
        Caption = "&Tools"
        Begin Menu mnuPencil
            Caption = "&Pencil"
            Checked = True
            RadioCheck = True
        End
        Begin Menu mnuEraser
            Caption = "&Eraser"
            RadioCheck = True
        End
        Begin Menu mnuPicker
            Caption = "Color Pic&ker"
            RadioCheck = True
        End
    End

    Begin Menu mnuSize
        Caption = "&Size"
        Begin Menu mnuSize16
            Caption = "16 x 16"
            RadioCheck = True
        End
        Begin Menu mnuSize24
            Caption = "24 x 24"
            RadioCheck = True
        End
        Begin Menu mnuSize32
            Caption = "32 x 32"
            Checked = True
            RadioCheck = True
        End
    End

    Begin Frame fraMain
        Caption = ""
        Layout  = HBox
        Weight  = 100

        Begin PictureBox cvEditor
            Width   = 256
            Height  = 256
            Weight  = 0
        End

        Begin Frame fraSidebar
            Caption = ""
            Layout  = VBox
            Width   = 100
            Weight  = 0

            Begin Label lblPreview
                Caption = "Preview:"
            End

            Begin PictureBox cvPreview
                Width   = 32
                Height  = 32
                Weight  = 0
            End

            Begin Label lblColor
                Caption = "Color:"
            End

            Begin PictureBox cvSelColor
                Width   = 32
                Height  = 20
                Weight  = 0
            End

            Begin Label lblPalette
                Caption = "Palette:"
            End

            Begin PictureBox cvPalette
                Width   = 80
                Height  = 80
                Weight  = 0
            End
        End
    End

    Begin Label lblStatus
        Caption = "Ready. (0, 0)"
        Height  = 16
        Weight  = 0
    End
End

OPTION EXPLICIT

CONST CANVAS_SIZE = 256
CONST BG_COLOR    = &H00C0C0C0
CONST GRID_COLOR  = &H00808080
CONST EDGE_COLOR  = &H00404040
CONST TOOL_PENCIL = 0
CONST TOOL_ERASER = 1
CONST TOOL_PICKER = 2
CONST PAL_COLS    = 8
CONST PAL_ROWS    = 4
CONST PAL_CELL    = 10

DIM pixels(31, 31) AS LONG
DIM palette(31) AS LONG
DIM iconW AS INTEGER
DIM iconH AS INTEGER
DIM pixelSize AS INTEGER
DIM curTool AS INTEGER
DIM curColor AS LONG
DIM drawing AS BOOLEAN
DIM dirty AS BOOLEAN
DIM filePath AS STRING

SUB InitPalette
    palette(0)  = &H00000000
    palette(1)  = &H00FFFFFF
    palette(2)  = &H00C0C0C0
    palette(3)  = &H00808080
    palette(4)  = &H00FF0000
    palette(5)  = &H00800000
    palette(6)  = &H00FF8000
    palette(7)  = &H00804000
    palette(8)  = &H00FFFF00
    palette(9)  = &H00808000
    palette(10) = &H0000FF00
    palette(11) = &H00008000
    palette(12) = &H0000FFFF
    palette(13) = &H00008080
    palette(14) = &H0000FF80
    palette(15) = &H00004040
    palette(16) = &H000000FF
    palette(17) = &H00000080
    palette(18) = &H008000FF
    palette(19) = &H00800080
    palette(20) = &H00FF00FF
    palette(21) = &H00FF0080
    palette(22) = &H00FF80C0
    palette(23) = &H004040FF
    palette(24) = &H00404040
    palette(25) = &H00A0A0A0
    palette(26) = &H00E0E0E0
    palette(27) = &H00FFE0C0
    palette(28) = &H00C0FFE0
    palette(29) = &H00C0E0FF
    palette(30) = &H00FFC0C0
    palette(31) = &H00C0C0FF
END SUB

SUB ClearPixels
    DIM x AS INTEGER
    DIM y AS INTEGER
    FOR y = 0 TO 31
        FOR x = 0 TO 31
            pixels(x, y) = BG_COLOR
        NEXT x
    NEXT y
    dirty = False
END SUB

SUB SetIconSize(w AS INTEGER)
    iconW     = w
    iconH     = w
    pixelSize = CANVAS_SIZE \ w
END SUB

SUB DrawEditorGrid
    DIM x AS INTEGER
    DIM y AS INTEGER
    DIM edgeW AS INTEGER
    cvEditor.Clear BG_COLOR
    FOR y = 0 TO iconH - 1
        FOR x = 0 TO iconW - 1
            cvEditor.FillRect x * pixelSize, y * pixelSize, pixelSize, pixelSize, pixels(x, y)
        NEXT x
    NEXT y
    FOR x = 0 TO iconW
        cvEditor.DrawLine x * pixelSize, 0, x * pixelSize, iconH * pixelSize, GRID_COLOR
    NEXT x
    FOR y = 0 TO iconH
        cvEditor.DrawLine 0, y * pixelSize, iconW * pixelSize, y * pixelSize, GRID_COLOR
    NEXT y
    edgeW = iconW * pixelSize
    cvEditor.DrawRect 0, 0, edgeW, edgeW, EDGE_COLOR
    cvEditor.Refresh
END SUB

SUB DrawPreview
    DIM x AS INTEGER
    DIM y AS INTEGER
    cvPreview.Clear BG_COLOR
    FOR y = 0 TO iconH - 1
        FOR x = 0 TO iconW - 1
            cvPreview.SetPixel x, y, pixels(x, y)
        NEXT x
    NEXT y
    cvPreview.Refresh
END SUB

SUB DrawPalette
    DIM i AS INTEGER
    DIM px AS INTEGER
    DIM py AS INTEGER
    cvPalette.Clear BG_COLOR
    FOR i = 0 TO 31
        px = (i MOD PAL_COLS) * PAL_CELL
        py = (i \ PAL_COLS) * PAL_CELL
        cvPalette.FillRect px, py, PAL_CELL, PAL_CELL, palette(i)
        cvPalette.DrawRect px, py, PAL_CELL, PAL_CELL, &H00000000
    NEXT i
    cvPalette.Refresh
END SUB

SUB DrawSelectedColor
    cvSelColor.Clear curColor
    cvSelColor.Refresh
END SUB

SUB RefreshAll
    DrawEditorGrid
    DrawPreview
    DrawSelectedColor
END SUB

SUB UpdateTitle
    DIM t AS STRING
    t = "DVX Icon Editor - " + STR$(iconW) + "x" + STR$(iconH)
    IF filePath <> "" THEN
        t = t + " - " + filePath
    END IF
    IF dirty THEN
        t = t + " *"
    END IF
    IconEd.Caption = t
END SUB

SUB SetIconPixel(x AS INTEGER, y AS INTEGER)
    DIM c AS LONG
    IF x < 0 OR x >= iconW OR y < 0 OR y >= iconH THEN
        EXIT SUB
    END IF
    IF curTool = TOOL_ERASER THEN
        c = BG_COLOR
    ELSE
        c = curColor
    END IF
    IF pixels(x, y) <> c THEN
        pixels(x, y) = c
        dirty = True
        UpdateTitle
        cvEditor.FillRect x * pixelSize, y * pixelSize, pixelSize, pixelSize, c
        cvEditor.DrawLine x * pixelSize, y * pixelSize, (x + 1) * pixelSize, y * pixelSize, GRID_COLOR
        cvEditor.DrawLine x * pixelSize, y * pixelSize, x * pixelSize, (y + 1) * pixelSize, GRID_COLOR
        cvEditor.DrawLine (x + 1) * pixelSize, y * pixelSize, (x + 1) * pixelSize, (y + 1) * pixelSize, GRID_COLOR
        cvEditor.DrawLine x * pixelSize, (y + 1) * pixelSize, (x + 1) * pixelSize, (y + 1) * pixelSize, GRID_COLOR
        cvPreview.SetPixel x, y, c
    END IF
END SUB

SUB SelectTool(t AS INTEGER)
    curTool = t
    IF t = TOOL_PENCIL THEN
        mnuPencil.Checked = True
        lblStatus.Caption = "Tool: Pencil"
    ELSEIF t = TOOL_ERASER THEN
        mnuEraser.Checked = True
        lblStatus.Caption = "Tool: Eraser"
    ELSEIF t = TOOL_PICKER THEN
        mnuPicker.Checked = True
        lblStatus.Caption = "Tool: Picker"
    END IF
END SUB

SUB ChangeSize(newSize AS INTEGER)
    DIM ans AS INTEGER
    IF newSize = iconW THEN
        EXIT SUB
    END IF
    IF dirty THEN
        ans = MsgBox("Unsaved changes will be lost. Change size?", vbYesNo)
        IF ans = vbNo THEN
            EXIT SUB
        END IF
    END IF
    SetIconSize newSize
    ClearPixels
    filePath = ""
    IF newSize = 16 THEN
        mnuSize16.Checked = True
    ELSEIF newSize = 24 THEN
        mnuSize24.Checked = True
    ELSE
        mnuSize32.Checked = True
    END IF
    UpdateTitle
    RefreshAll
    lblStatus.Caption = STR$(iconW) + "x" + STR$(iconH) + " - Ready."
END SUB

SUB IconEd_Load
    InitPalette
    SetIconSize 32
    ClearPixels
    curTool  = TOOL_PENCIL
    curColor = &H00000000
    drawing  = False
    filePath = ""
    DrawPalette
    RefreshAll
    UpdateTitle
END SUB

SUB mnuNew_Click
    DIM ans AS INTEGER
    IF dirty THEN
        ans = MsgBox("Unsaved changes. Start new icon?", vbYesNo)
        IF ans = vbNo THEN
            EXIT SUB
        END IF
    END IF
    ClearPixels
    filePath = ""
    UpdateTitle
    RefreshAll
END SUB

SUB mnuOpen_Click
    DIM ans AS INTEGER
    DIM path AS STRING
    DIM x AS INTEGER
    DIM y AS INTEGER
    IF dirty THEN
        ans = MsgBox("Unsaved changes. Open another file?", vbYesNo)
        IF ans = vbNo THEN
            EXIT SUB
        END IF
    END IF
    path = InputBox$("Open BMP file:", "Open Icon", filePath)
    IF path = "" THEN
        EXIT SUB
    END IF
    cvPreview.Load path
    FOR y = 0 TO iconH - 1
        FOR x = 0 TO iconW - 1
            pixels(x, y) = cvPreview.GetPixel(x, y)
        NEXT x
    NEXT y
    filePath = path
    dirty = False
    UpdateTitle
    RefreshAll
END SUB

SUB mnuSave_Click
    DIM path AS STRING
    IF filePath = "" THEN
        path = InputBox$("Save BMP file:", "Save Icon", "ICON.BMP")
    ELSE
        path = InputBox$("Save BMP file:", "Save Icon", filePath)
    END IF
    IF path = "" THEN
        EXIT SUB
    END IF
    DrawPreview
    cvPreview.Save path
    filePath = path
    dirty = False
    UpdateTitle
    lblStatus.Caption = "Saved: " + path
END SUB

SUB mnuExit_Click
    Unload IconEd
END SUB

SUB mnuPencil_Click
    SelectTool TOOL_PENCIL
END SUB

SUB mnuEraser_Click
    SelectTool TOOL_ERASER
END SUB

SUB mnuPicker_Click
    SelectTool TOOL_PICKER
END SUB

SUB mnuSize16_Click
    ChangeSize 16
END SUB

SUB mnuSize24_Click
    ChangeSize 24
END SUB

SUB mnuSize32_Click
    ChangeSize 32
END SUB

SUB cvEditor_MouseDown(button AS INTEGER, x AS INTEGER, y AS INTEGER)
    DIM px AS INTEGER
    DIM py AS INTEGER
    px = x \ pixelSize
    py = y \ pixelSize
    IF curTool = TOOL_PICKER THEN
        IF px >= 0 AND px < iconW AND py >= 0 AND py < iconH THEN
            curColor = pixels(px, py)
            DrawSelectedColor
            SelectTool TOOL_PENCIL
        END IF
        EXIT SUB
    END IF
    drawing = True
    SetIconPixel px, py
    lblStatus.Caption = "(" + STR$(px) + "," + STR$(py) + ")"
END SUB

SUB cvEditor_MouseMove(button AS INTEGER, x AS INTEGER, y AS INTEGER)
    DIM px AS INTEGER
    DIM py AS INTEGER
    px = x \ pixelSize
    py = y \ pixelSize
    IF px >= 0 AND px < iconW AND py >= 0 AND py < iconH THEN
        lblStatus.Caption = "(" + STR$(px) + "," + STR$(py) + ")"
    END IF
    IF drawing THEN
        SetIconPixel px, py
    END IF
END SUB

SUB cvEditor_MouseUp(button AS INTEGER, x AS INTEGER, y AS INTEGER)
    drawing = False
END SUB

SUB IconEd_QueryUnload(Cancel AS INTEGER)
    IF NOT dirty THEN
        EXIT SUB
    END IF
    DIM result AS INTEGER
    result = basPromptSave("Icon Editor")
    IF result = DVX_SAVE_YES THEN
        mnuSave_Click
        IF dirty THEN
            Cancel = 1
        END IF
    ELSEIF result = DVX_SAVE_CANCEL THEN
        Cancel = 1
    END IF
END SUB


SUB cvPalette_MouseDown(button AS INTEGER, x AS INTEGER, y AS INTEGER)
    DIM col AS INTEGER
    DIM row AS INTEGER
    DIM idx AS INTEGER
    col = x \ PAL_CELL
    row = y \ PAL_CELL
    IF col >= 0 AND col < PAL_COLS AND row >= 0 AND row < PAL_ROWS THEN
        idx = row * PAL_COLS + col
        curColor = palette(idx)
        DrawSelectedColor
        IF curTool = TOOL_PICKER THEN
            SelectTool TOOL_PENCIL
        END IF
    END IF
END SUB
