Page 1 of 1

Custom grid gadget

Posted: Tue Nov 27, 2007 10:25 pm
by Mistrel
It's not really a gadget but I wasn't sure what else to call it. Thanks to srod for helping me sort out the window callback.

Code: Select all

Enumeration
	#main_window
	#grid_image
EndEnumeration

Global glob_x=33
Global glob_y=33
Global glob_sectorwidth=32
Global glob_borderwidth=1

Procedure DrawSectorGrid(x,y)
  If StartDrawing(WindowOutput(#main_window))
		width=WindowWidth(#main_window)
		height=WindowHeight(#main_window)
		borderwidth=glob_borderwidth
		sectorwidth=glob_sectorwidth+borderwidth
		glob_x=x
		glob_y=y

    Box(0,0,width,height,RGB(255,255,255))
		offsety=height-(y%(sectorwidth))
		n=((x+((x/sectorwidth)-((x+(x/sectorwidth))/sectorwidth)))/sectorwidth)
		If (n/2)+(n/2)=n ; even
			offsetx=(x%sectorwidth)-sectorwidth
		Else ; odd
			offsetx=(x%sectorwidth)-(sectorwidth*2)
		EndIf

    i=0 : Repeat
    	Box(offsetx+i+borderwidth-1,0,sectorwidth-1,height,RGB(247,247,247))
    	i+sectorwidth*2;+2
    Until i>width+(sectorwidth*2)
    
    For n=0 To borderwidth-1
	    i=0 : Repeat
	    	LineXY(offsetx+i+sectorwidth+n-1,0,offsetx+i+sectorwidth+n-1,height,RGB(220,220,220))
	    	LineXY(offsetx+i+n-1,0,offsetx+i+n-1,height,RGB(220,220,220))
	    	i+sectorwidth*2;+2
	    Until i>width+(sectorwidth*2)
    Next n
    
    For n=0 To borderwidth-1
	    i=0 : Repeat
				LineXY(0,offsety-i+n,width,offsety-i+n,RGB(220,220,220))
	    	i+(sectorwidth)
	    Until i>height+(sectorwidth)
    Next n
    
    For n=0 To borderwidth-1
	    LineXY(x-1+n,0,x-1+n,height,RGB(141,141,141))
	    LineXY(0,height-y+n,width,height-y+n,RGB(141,141,141))
    Next n
    StopDrawing()
  EndIf
EndProcedure

Procedure MouseMoveX(reset=0)
   Static lastx
   Static callflag
   If reset
      callflag=0
      ProcedureReturn 0
   EndIf
   If Not callflag ; if this procedure has not been called before
      callflag=1
      lastx=DesktopMouseX()
      ProcedureReturn 0
   EndIf
   n=lastx
   lastx=DesktopMouseX()
   ProcedureReturn DesktopMouseX()-n
EndProcedure

Procedure MouseMoveY(reset=0)
   Static lasty
   Static callflag
   If reset
      callflag=0
      ProcedureReturn 0
   EndIf
   If Not callflag ; if this procedure has not been called before
      callflag=1
      lasty=DesktopMouseY()
      ProcedureReturn 0
   EndIf
   n=lasty
   lasty=DesktopMouseY()
   ProcedureReturn DesktopMouseY()-n
EndProcedure

Procedure ClearMouseMove()
   MouseMoveX(1)
   MouseMoveY(1)
EndProcedure

Procedure.l WinCallback(hWnd,uMsg,wParam,lParam)
  result=#PB_ProcessPureBasicEvents
  GetCursorPos_(@cp.point)
  Select uMsg
    Case #WM_SIZE
    	If hWnd=WindowID(#main_window)
      	InvalidateRect_(hWnd,0,1) ; forces #WM_PAINT for this window
      EndIf
    Case #WM_LBUTTONUP
    	If hWnd=WindowID(#main_window)
      	ClearMouseMove()
    	EndIf
    Case #WM_PAINT
    	If hWnd=WindowID(#main_window)
			  DrawSectorGrid(glob_x,glob_y)
				ValidateRect_(hWnd, 0)
			EndIf
		Case #WM_ERASEBKGND
			If hWnd=WindowID(#main_window)
				result=1 ; do not erase the background of this window when invalidated
			EndIf
    Case #WM_MOUSEMOVE
      If wParam=#MK_LBUTTON
        GetWindowRect_(WindowID(#main_window),gr.RECT)
        If PtInRect_(@gr,cp\x,cp\y)
          glob_x+MouseMoveX()
          glob_y-MouseMoveY()
          InvalidateRect_(hWnd,0,1) ; forces #WM_PAINT for this window
        EndIf
      EndIf
		Case #WM_MOUSEWHEEL
			GetWindowRect_(WindowID(#main_window),gr.RECT)
      If PtInRect_(@gr,cp\x,cp\y) And hWnd=WindowID(#main_window)
				If wparam>0 ; up
					glob_sectorwidth+1 ; increase sector width
				Else  ; down
					glob_sectorwidth-1 ; decrease sector width
					If glob_sectorwidth<4
						glob_sectorwidth=4
					EndIf
				EndIf
				InvalidateRect_(hWnd,0,1) ; forces #WM_PAINT for this window
			EndIf
    Default
  EndSelect
  ProcedureReturn result
EndProcedure

If OpenWindow(#main_window,100,200,300,300,"Sector Overview",#PB_Window_SizeGadget)
	SmartWindowRefresh(#main_window,#True) 
	DrawSectorGrid(glob_x+1,glob_y+1)
  SetWindowCallback(@WinCallback())
  
  Repeat
    EventID=WaitWindowEvent()
    If EventID
    	Select EventID
    		Case #PB_Event_CloseWindow
    			End
				Default
					x=glob_x
					y=glob_y
					borderwidth=glob_borderwidth
					sectorwidth=glob_sectorwidth+glob_borderwidth
					width=WindowWidth(#main_window)
					height=WindowHeight(#main_window)
					GetCursorPos_(@cp.point)
					GetWindowRect_(WindowID(#main_window),gr.RECT)
					If PtInRect_(@gr, cp\x, cp\y)
			      MapWindowPoints_(#Null, WindowID(#main_window),cp,1) ; cp now contains window coords
			      If GetAsyncKeyState_(#VK_RBUTTON)&32768
							originx=x-1+borderwidth ; the absolute position of the grid origin x in pixels
							originy=height-y ; the absolute position of the grid origin y in pixels
							originy_flipped=height-originy ; the absolute position of the grid origin y in pixels where 0 is the bottom of the window
							;Debug "Origin: x "+Str(originx)+" y "+Str(originy)+" ("+Str(originy_flipped)+")"
							mousex=cp\x ; the position of the mouse relative to the window in pixels
							mousey=cp\y ; the position of the mouse relative to the window in pixels
							mousey_flipped=height-mousey  ; the position of the mouse relative to the window in pixels where 0 is the bottom of the window
							;Debug "Mouse pos: x"+Str(mousex)+" y "+Str(mousey)+" ("+Str(mousey_flipped)+")" ; the mouse position relative to the window
							localx=mousex-glob_x ; the local mouse position relative to the grid origin in pixels
							localy=height-mousey-glob_y ; the local mouse position relative to the grid origin in pixels
							;Debug "Local pos: x"+Str(localx) +" y "+Str(localy) ; the mouse position relative to the grid origin in pixels
							sectorx=localx/sectorwidth ; the absolute grid sector x currently being hovered over by the mouse
			      	sectory=localy/sectorwidth ; the absolute grid sector y currently being hovered over by the mouse
			      	Debug "Sector "+Str(sectorx) +","+Str(sectory) ; the mouse position relative to the grid origin in pixels
			      	sectorx_localpos=originx+(localx/sectorwidth)*sectorwidth ; the local x position to the window in pixels of the grid sector currently hovered over with by mouse
			      	sectory_localpos=originy-(localy/sectorwidth)*sectorwidth ; the local y position to the window in pixels of the grid sector currently hovered over with by mouse

			      	StartDrawing(WindowOutput(#main_window))
			      	; these are minor adjustments to the final position of the box to that it will fit inside of its borders and not on top of them
			      	; this is also used to identify which quadrant the sector is located in
			      	If localx>=0 And localy>=0
			      		x_sectorwidth=sectorwidth-borderwidth
			      		y_sectorwidth=0-(sectorwidth-borderwidth)
			      		quadrant=1
			      	ElseIf localx<0 And localy>=0
			      		x_sectorwidth=0-(sectorwidth-borderwidth)
			      		y_sectorwidth=0-(sectorwidth-borderwidth)
			      		sectorx_localpos-borderwidth
			      		quadrant=2
			      	ElseIf localx<0 And localy<0
			      		x_sectorwidth=0-(sectorwidth-borderwidth)
			      		y_sectorwidth=sectorwidth-borderwidth
			      		sectorx_localpos-borderwidth
			      		sectory_localpos+borderwidth
			      		quadrant=3
			      	ElseIf localx>=0 And localy<0
			      		x_sectorwidth=sectorwidth-borderwidth
			      		y_sectorwidth=sectorwidth-borderwidth
			      		sectory_localpos+borderwidth
			      		quadrant=4
			      	EndIf
			      	;Debug "Quadrant: "+Str(quadrant)
			      	
							Box(sectorx_localpos,sectory_localpos,x_sectorwidth,y_sectorwidth,RGB(Random(255),Random(255),Random(255)))
							StopDrawing()
			      EndIf ; endif #VK_RBUTTON
			      If GetAsyncKeyState_(#VK_LBUTTON)&32768

						EndIf
			   EndIf
    	EndSelect
    EndIf
  ForEver
EndIf

Posted: Sun Jan 13, 2008 9:39 pm
by kawasaki
This is brilliant.

Great work :D

Posted: Sun Jan 13, 2008 9:45 pm
by Hroudtwolf
Hi,

Nice idea.
But how do you want to create more than one instances of this gridcontrol?
A encapsulation is very needed for a GUI-control.

Best regards

Wolf

Posted: Sun Jan 13, 2008 11:19 pm
by Kwai chang caine
Very very great. :shock:
I need this code for a long time ago 8)

But i have two questions :

1 / Is it possible to write any character in the case of grid ?

2 / Is it normal that the color disappears when you move the grid with the mouse ?

Thanks again for shared this great code

Posted: Mon Jan 14, 2008 8:00 am
by Mistrel
I'm planning to revisit this after my current project. It has its flaws but it will shave of a lot of time for anyone who might otherwise need a control-like grid for whatever.

I hope it's still useful to some people in its current form.

Posted: Mon Jan 14, 2008 12:04 pm
by #NULL
on rightclicks the debug-output shows the negative indices start with 0 too, like:
-2, -1, 0, 0, 1, 2
so you have four zeros and your negative x- or y-values always are always one too high.
i just recognized, but maybe it's supposed to work like that (?)

Posted: Tue Jan 15, 2008 4:01 am
by Mistrel
#NULL wrote:on rightclicks the debug-output shows the negative indices start with 0 too, like:
-2, -1, 0, 0, 1, 2
so you have four zeros and your negative x- or y-values always are always one too high.
i just recognized, but maybe it's supposed to work like that (?)
I designed it this way because I store the quadrant number in addition to the actual cell position. This makes sense in a grid because 0 is always 0 no matter which quadrant you're in. :)