Re: Spreadsheet Control
- Posted by "Cuny, David at DSS" <David.Cuny at DSS.CA.GOV> Apr 18, 2000
- 502 views
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 )