A Picture in a Button

Jim Mahoney, November 2004

This notebook shows an example of a clickable button with a picture in it.

There must be a cell in the notebook whose CellTag is the same as the global variable whichCellTag; 
that cell is replaced each time the button is clicked so that any changes to the button's appearence are shown.

To make more buttons with various properties, or turn this into a board for a game, change the makeButton
function to take an argument ( [row_, column_] perhaps) and have it draw different pictures and/or do 
different things in different places.

Code

(* Set up global variables and draw the button. *)
init:= Module[{},
		colorOne = RGBColor[0,1,1];						(* These colors are swapped when the button is pushed. *)
		colorTwo = RGBColor[1,1,0];
		g := Graphics[									(* The graphic that'll be shown in the button. *)
			{	colorOne,
				Polygon[{{0,5},{5,10},{10,5},{5,0}}],		(* outer diamond *)
				colorTwo,
				Polygon[{{4,4},{4,6},{6,6},{6,4}}]			(* inner square *)
          		},
        	PlotRange->{{0,10},{0,10}},						(* graph coords are (x,y) from (0,0) to (10,10) *)
        	AspectRatio->1,
        	ImageSize->{40,40}								(* picture will be 40 pixels by 40 pixels *)
        	];
        whichCellTag = "theButtonCell";					(* The CellTag of the cell where the button is. *)
        buttonPushed = False;							(* This is flipped each time the button is pushed. *)
        theButtonFrame = "None";						(* This is also flipped when the button is pushed. *)
        drawButton;
        ];
        
(* What to do when the button is clicked. *)
doButtonClick[] := Module[{}, 
	buttonPushed = ! buttonPushed;
	{colorOne, colorTwo} = {colorTwo, colorOne};
	If[ buttonPushed, 
		(*then*) theButtonFrame = "Palette", 
		(*else*) theButtonFrame = "None" ];
	drawButton;
	];	
	
(* Return the stuff that should be shown within the button. *)
makeButtonContent := Cell[GraphicsData["PostScript",DisplayString[g]]];

(* Return the button. *)
makeButton := ButtonBox[
	makeButtonContent,
	ButtonFunction :> doButtonClick[],
	ButtonEvaluator -> Automatic,
	Active -> True,
	ButtonStyle -> "None",
	ButtonFrame -> theButtonFrame
	];

(* Return the cell that has the button in it.
   To make an array of buttons or whatever else
   just put more stuff in list of lists within the GridBox  *)
makeButtonCell := Cell[
	BoxData[GridBox[{{ makeButton }}]],
	CellTags -> whichCellTag
	];
 
(* In the current notebook, find whichCell and replace it with the output of makeButtonCell. *)
drawButton := Module[{nb},
	nb = SelectedNotebook[];
	NotebookFind[nb,whichCellTag,All,CellTags];
	NotebookWrite[nb, makeButtonCell, All];
	];

(* Set everything up. *)
init;

The Button

So click on the picture below already.  
Three things will happen : (a) the frame around the button changes, (b) the colors flip, (c) the value of buttonPushed flips.
(Are we having fun yet?)