Re: Spreadsheet Control

new topic     » goto parent     » topic index » view thread      » older message » newer message

Urgh. There were a few bugs in the code, such as not actually using gridData
to display the code.

I also added system colors and double-buffering, so the display should be
smoother.

-- David Cuny

-- grid.exw
-- emulated spreadsheet-type grid control

include win32lib.ew

constant
    CellCX      = 64,           -- cell width
    CellCY      = 20            -- cell height

integer
    grid,           -- id of grid
    gridPix,        -- image of grid
    gridOwner,      -- parent of grid
    gridCols,       -- number of displayed columns
    gridRows,       -- number of displayed rows
    gridMaxCols,    -- max number of columns
    gridMaxRows,    -- max number of rows
    gridX,          -- x position of grid
    gridY,          -- y position of grid
    gridCX,         -- width of grid
    gridCY,         -- height of grid
    gridV,          -- grid vertical scroll bar
    gridH,          -- grid horizontal scroll bar
    cellX,          -- current cell x
    cellY           -- current cell y

global sequence
    gridData

global procedure paintGrid()
    -- draw the grid control
    integer x, y, x2, y2, offsetX, offsetY, thisX, thisY, h, v
    sequence size

    -- size of font
    size = getFontSize( gridOwner )

    -- to center in cell
    offsetY = floor( (CellCY - size[2])/2 )

    -- cell index
    h = getScrollPos( gridH ) - 1
    v = getScrollPos( gridV ) - 1

    -- current cell
    x = 0
    y = 0

    -- background
    setPenColor( gridPix, getSysColor( COLOR_BTNFACE ) )
    drawRectangle( gridPix, True, 1, 1, gridCX, gridCY )


    -- draw each cell
    for y1 = 0 to gridCY-1 by CellCY do

        for x1 = 0 to gridCX-1 by CellCX do

            x2 = x1 + CellCX - 1
            y2 = y1 + CellCY - 1

            -- draw the cell
            if x = 0 or y = 0 then

                -- background
                setPenColor( gridPix, getSysColor( COLOR_BTNFACE ) )
                drawRectangle( gridPix, True, x1, y1, x2+1, y2+1 )
                setPenColor( gridPix, getSysColor( COLOR_GRAYTEXT ) )
                drawRectangle( gridPix, False, x1, y1, x2, y2 )

                -- selected col/row?
                if h+x = cellX or v+y = cellY then

                    -- highlight
                    setPenColor( gridPix, getSysColor( COLOR_BTNHIGHLIGHT )
)
                    drawLine( gridPix, x1, y1, x2, y1 )
                    drawLine( gridPix, x1, y1, x1, y2 )

                    -- shadow
                    setPenColor( gridPix, getSysColor( COLOR_3DDKSHADOW ) )
                    drawLine( gridPix, x2, y1, x2, y2 )
                    drawLine( gridPix, x1, y2, x2, y2 )

                    setPenColor( gridPix, getSysColor( COLOR_BTNSHADOW ) )
                    drawLine( gridPix, x2-1, y1+1, x2-1, y2-1 )
                    drawLine( gridPix, x1+1, y2-1, x2-1, y2-1 )


                end if

            else
                -- cell
                setPenColor( gridPix, getSysColor( COLOR_WINDOW ) )
                drawRectangle( gridPix, True, x1, y1, x2, y2 )
                setPenColor( gridPix, COLOR_GRAYTEXT )
                drawLine( gridPix, x2, y1, x2, y2 )
                drawLine( gridPix, x1, y2, x2, y2 )

                -- selected?
                if x+h = cellX and y+v = cellY then
                    setPenColor( gridPix, getSysColor( COLOR_BTNTEXT ) )
                    for i = 0 to 1 do
                        drawRectangle( gridPix, False, x1+i, y1+i, x2-i,
y2-i )
                    end for

                end if

            end if

            -- text in the cell
            if x = 0 and y = 0  then
                -- no text

            elsif x = 0 then
                setPosition( gridPix, x1+4, y1+offsetY )
                wPrintf( gridPix, "%d", {y+v} )

            elsif y = 0 then
                setPosition( gridPix, x1+4, y1+offsetY )
                wPrintf( gridPix, "%s", "A"+x+h-1 )

            else
                setPosition( gridPix, x1+4, y1+offsetY )
                wPuts( gridPix, gridData[x+h][y+v] )
            end if


            -- increment cell index
            x += 1

        end for

        -- increment cell index
        x = 0
        y += 1

    end for

    -- copy the pixmap
    copyBlt( gridOwner, gridX, gridY, gridPix )

end procedure

procedure paint( integer x1, integer y1, integer x2, integer y2 )
    paintGrid()
end procedure

procedure mouse( integer event, integer x, integer y, integer shift )

    if event = LeftDown then
        -- in the grid?
        if x >= gridX and y >= gridY
        and x < gridX+gridCX and y < gridY+gridCY then

            -- which cell?
            x = floor( (x-gridX)/CellCX )
            y = floor( (y-gridY)/CellCY )

            if x != 0 and y != 0 then
                -- cell index
                cellX = getScrollPos( gridH ) + x - 1
                cellY = getScrollPos( gridV ) + y - 1

            end if

            -- update the grid
            paint( 0, 0, 0, 0 )

            -- focus on hidden control
            setFocus( grid )

        end if

    end if

end procedure

procedure keydown( integer keycode, integer shift )

    -- key handler for scrollbar

    integer h, v

    if keycode = VK_HOME then
        cellX = 1
        cellY = 1
        setScrollPos( gridH, 1 )
        setScrollPos( gridV, 1 )

    elsif keycode = VK_LEFT then

        if cellX > 1 then

            -- move cell
            cellX -= 1

            -- need to scroll?
            h = getScrollPos( gridH )
            if h > cellX then
                -- scroll
                setScrollPos( gridH, cellX )
            else
                -- just paint
                paintGrid()
            end if
        end if

    elsif keycode = VK_RIGHT then

        -- check range
        if cellX < gridMaxCols then

            -- move cell
            cellX += 1

            -- need to scroll?
            h = getScrollPos( gridH )
            if h + gridCols - 1 < cellX then
                -- scroll
                setScrollPos( gridH, h+1 )
            else
                -- just paint
                paintGrid()
            end if

        end if

    elsif keycode = VK_UP then
        if cellY > 1 then

            -- move
            cellY -= 1

            -- need to scroll?
            if getScrollPos( gridV ) > cellY then
                setScrollPos( gridV, cellY )
            else
                paintGrid()
            end if
        end if

    elsif keycode = VK_DOWN then

        -- check range
        if cellY < gridMaxRows then

            -- move cell
            cellY += 1

            -- need to scroll?
            v = getScrollPos( gridV )
            if v + gridRows - 1 < cellY then
                -- scroll
                setScrollPos( gridV, v+1 )
            else
                -- just paint
                paintGrid()
            end if

        end if


    end if

    -- don't give to the mle
    returnValue( True )

end procedure

procedure scrollbar( integer pos )
    -- update the grid
    paint( 0, 0, 0, 0 )

    -- focus on hidden control
    setFocus( grid )

end procedure

procedure createGrid( integer owner, integer x, integer y,
                        integer rows, integer cols,
                        integer maxRows, integer maxCols )

    -- save values
    gridOwner   = owner
    gridX       = x
    gridY       = y
    gridCols    = rows
    gridRows    = cols
    gridMaxCols = maxRows
    gridMaxRows = maxCols
    gridCX      = (gridCols+1) * CellCX
    gridCY      = (gridRows+1) * CellCY

    -- allocate space for data
    gridData = repeat( repeat( "", gridMaxCols ), gridMaxRows )

    -- create controls
    grid  = create( MleText, "", gridOwner, -10, -10, 5, 5, 0 )
    gridV = create( VScroll, "", gridOwner, gridX+gridCX, gridY, 16, gridCY,
0 )
    gridH = create( HScroll, "", gridOwner, gridX, gridY+gridCY, gridCX, 16,
0 )
    gridPix = create( Pixmap, "", 0, 0, 0, gridCX, gridCY, 0 )

    -- scroll range
    setScrollRange( gridV, 1, (gridMaxRows - gridRows) + 1 )
    setScrollRange( gridH, 1, (gridMaxCols - gridCols) + 1 )

    -- selected cell
    cellX = 1
    cellY = 1

    -- set up callbacks
    onPaint[gridOwner]  = routine_id("paint")
    onMouse[gridOwner]  = routine_id("mouse")
    onKeyDown[grid]     = routine_id("keydown")
    onScroll[gridH]     = routine_id("scrollbar")
    onScroll[gridV]     = routine_id("scrollbar")

    -- draw the control
    paintGrid()

end procedure


-- demo
constant Win = create( Window, "Grid Demo", 0, Default, Default, 360, 180, 0
)

-- create the grid
createGrid( Win, 10, 10, 4, 4, 10, 10 )

function pick( sequence s )
    return s[ rand( length(s) ) ]
end function

-- fill it with data
for y = 1 to 10 do
    for x = 1 to 10 do
        for i = 1 to 4 + rand(10) do
            gridData[y][x] &= pick("qwertyuiopasdfghjklzxcvbnm")
        end for
    end for
end for

WinMain( Win, Normal )

new topic     » goto parent     » topic index » view thread      » older message » newer message

Search



Quick Links

User menu

Not signed in.

Misc Menu