Public doFontFace, fontFace, doFontSize, fontSizeOpt, relVal, absVal
Sub Main
	
	'Font properties to use
	doFontFace = True ' true to do the font face changes
	doFontSize = True ' true to do the font size changes
	fontSizeOpt = 1 ' 0=relative, 1=absolute
	fontFace = "Arial"
	relVal = -2 'negative values will make it smaller
	absVal = 12

	'Comment this out if you want to just define the specifications above and not use a dialog to get them
	AskUserForFontProperties()

	'-----------------------------------------------------------------------------------------------------------
	
	'Do this for the currently active document
	Dim Grapher As Object
	Set Grapher = CreateObject("Grapher.Application")
	Set doc = Grapher.Documents.Active

	'Loop through all objects in this document and adjust the font properties
	For i = 1 To doc.shapes.count
		Set docObj = doc.shapes.item(i)

		'Go through all group objects as well, this does not check for nested groups
		If docObj.Type = grfShapeComposite Then
			For g = 1 To docObj.Shapes.Count
				ProcessShape(docObj.Shapes.Item(g))
			Next
		Else
			ProcessShape(docObj)
		End If
	Next
End Sub

Function ProcessShape(docObj As Object)
		'GRAPH
		If docObj.type = grfShapeGraph Then
			SetFont(docObj.Title.Font) ' graph title

			'PLOT
			For j = 1 To docObj.plots.count
				Set plotObj = docObj.plots.item(j)
				On Error GoTo ignore 'some plots specify these differently or don't have color scales
				SetFont(plotObj.labels.font) ' plot labels
				SetFont(plotObj.labels.format.PrefixMT) 'prefix labels
				SetFont(plotObj.labels.format.PostfixMT) 'postfix labels
				SetFont(plotObj.labelfont) 'plot labels
				SetFontBoxPlot(plotObj) 'box plot labels
				SetFont(plotObj.ColorScale.title.font) 'color scale title
				SetFont(plotObj.ColorScale.font) 'color scale labels
				On Error GoTo 0
				SetFont(plotObj.title.font) 'plot title
			Next

			'AXIS
			For k = 1 To docObj.axes.count
				Set axesObj = docObj.axes.item(k)
				SetFont(axesObj.title.font) 'axis title
				SetFont(axesObj.ticklabels.majorfont) 'axis major tick labels
				SetFont(axesObj.ticklabels.majorformat.PrefixMT) 'major prefix
				SetFont(axesObj.ticklabels.majorformat.PostfixMT) 'major postfix
				On Error GoTo ignore 'some axes don't use minor labels
				SetFont(axesObj.ticklabels.minorfont) 'axis minor tick labels
				SetFont(axesObj.ticklabels.minorformat.PrefixMT) 'minor prefix
				SetFont(axesObj.ticklabels.minorformat.PostfixMT) 'minor postfix
				On Error GoTo 0
			Next

			'PLOT LEGEND
			For m = 1 To docObj.legends.count
				Set legendObj = docObj.legends.item(m)
				SetFont(legendObj.title.font) 'legend title
				SetFont(legendObj.font) 'plot legend all entries
				For n = 1 To legendObj.EntryCount
					SetFont(legendObj.EntryFont(n)) 'plot legend individual entries
				Next
			Next

		'MULTI-GRAPH LEGEND
		ElseIf docObj.Type = grfShapeLegend Then
			On Error GoTo ignore 'some legends specify these differently
			SetFont(docObj.title.font) 'legend all entries
			SetFont(docObj.titlefont) 'legend title
			SetFont(docObj.labelfont) 'pie entries
			On Error GoTo 0
			For j = 1 To docObj.EntryCount
				SetFont(docObj.EntryFont(j)) 'legend individual entries
			Next

		'TEXT OBJECT
		ElseIf docObj.Type = grfShapeText Then
			SetFont(docObj.font) 'text

		'PIE CHART
		ElseIf docObj.type = grfShapePieChart Or docObj.type = grfShapeDoughnutPlot Then
			SetFont(docObj.title.font) 'pie title
			SetFont(docObj.firstlinefont) 'primary labels
			SetFont(docObj.secondlinefont) 'secondary labels
		End If

		Exit Function
	ignore :
		' Do nothing here.  This is just a way to skip over errors if the font automation method isn't available on the particular object instead of making
		' a bunch of if/else clauses on the type of objects and handling them differently
		Resume Next
End Function


Function SetFont(font As Object)
	If (doFontFace) Then
		font.Face = fontFace
	End If

	If (doFontSize) Then
		Select Case fontSizeOpt
		Case 0 'relative
			font.Size = font.Size + Val(relVal)
		Case 1 'absolute
			font.Size = Val(absVal)
		End Select
	End If
End Function

Function SetFontBoxPlot(plot As Object)
	SetFont(plot.MaxFont)
	SetFont(plot.MaxFormat.PrefixMT)
	SetFont(plot.MaxFormat.PostfixMT)
	SetFont(plot.MedianFont)
	SetFont(plot.MedianFormat.PrefixMT)
	SetFont(plot.MedianFormat.PostfixMT)
	SetFont(plot.MinFont)
	SetFont(plot.MinFormat.PrefixMT)
	SetFont(plot.MinFormat.PostfixMT)
	SetFont(plot.NotchesFont)
	SetFont(plot.NotchesFormat.PrefixMT)
	SetFont(plot.NotchesFormat.PostfixMT)
	SetFont(plot.OutliersFont)
	SetFont(plot.OutliersFormat.PrefixMT)
	SetFont(plot.OutliersFormat.PostfixMT)
	SetFont(plot.Quartiles25Font)
	SetFont(plot.Quartiles25Format.PrefixMT)
	SetFont(plot.Quartiles25Format.PostfixMT)
	SetFont(plot.Quartiles75Font)
	SetFont(plot.Quartiles75Format.PrefixMT)
	SetFont(plot.Quartiles75Format.PostfixMT)
	SetFont(plot.SamplesFont)
	SetFont(plot.SamplesFormat.PrefixMT)
	SetFont(plot.SamplesFormat.PostfixMT)
	SetFont(plot.WhiskersLowerFont)
	SetFont(plot.WhiskersLowerFormat.PrefixMT)
	SetFont(plot.WhiskersLowerFormat.PostfixMT)
	SetFont(plot.WhiskersUpperFont)
	SetFont(plot.WhiskersUpperFormat.PrefixMT)
	SetFont(plot.WhiskersUpperFormat.PostfixMT)
End Function


' Present a dialog to ask the user for font properties to change.  To adjust the dialog: in Scripter, put the cursor somewhere between Begin/End Dialog
' and click Edit | UserDialog Editor... from the menu
Function AskUserForFontProperties()
	'User dialog to ask for input
	Begin Dialog UserDialog 290, 147, "Update Fonts in Document", .DialogFunc ' %GRID:10,7,1,1
		Text 30, 42, 70, 21, "Font face:", .Text1
		TextBox 110, 42, 170, 21, .font_face
		Text 30, 70, 60, 14, "Font size:", .Text2
		OKButton 210, 119, 70, 21
		Text 10, 7, 270, 28, "Set the font face and/or size for the fonts throughout the active document. ", .Text3
		CheckBox 10, 42, 20, 14, "", .do_font_face
		CheckBox 10, 70, 20, 14, "", .do_font_size
		OptionGroup .SizeOption
			OptionButton 110, 70, 80, 14, "Relative", .size_relative
			OptionButton 200, 70, 80, 14, "Absolute", .size_absolute
		TextBox 110, 91, 70, 14, .relative_val
		TextBox 200, 91, 80, 14, .absolute_val
	End Dialog

	Dim dlg As UserDialog
	dlg.do_font_face = doFontFace
	dlg.font_face = fontFace
	dlg.do_font_size = doFontSize
	dlg.SizeOption = fontSizeOpt
	dlg.relative_val = relVal
	dlg.absolute_val = absVal

	result = Dialog(dlg)
	If (result = -1) Then ' OK pressed
		doFontFace = dlg.do_font_face
		If dlg.font_face <> "" Then fontFace = dlg.font_face
		doFontSize = dlg.do_font_size
		fontSizeOpt = dlg.SizeOption
		relVal = dlg.relative_val
		absVal = dlg.absolute_val
	End If
End Function

' Helper function to process functions in the dialog
Function DialogFunc(DlgItem$, Action%, SuppValue&) As Boolean
	Select Case Action
	Case 1 'initialize the visible state based on the default
		If fontSizeOpt = 0 Then
				DlgVisible "relative_val", True
				DlgVisible "absolute_val", False
		Else
				DlgVisible "relative_val", False
				DlgVisible "absolute_val", True
		End If

	Case 2 ' check for radio buttons or check boxes clicked on to hide/show features
		Select Case DlgItem
		Case "SizeOption"
			Select Case SuppValue
			Case 0 'relative
				DlgVisible "relative_val", True
				DlgVisible "absolute_val", False
			Case 1 'absolute
				DlgVisible "relative_val", False
				DlgVisible "absolute_val", True
			End Select

		Case "do_font_face"
			Select Case SuppValue
			Case 0 'off
				DlgVisible "font_face", False
			Case 1 'on
				DlgVisible "font_face", True
			End Select

		Case "do_font_size"
			Select Case SuppValue
			Case 0 'off
				DlgValue "SizeOption", -1
				DlgVisible "SizeOption", False
				DlgVisible "relative_val", False
				DlgVisible "absolute_val", False
			Case 1 'on
				DlgVisible "SizeOption", True
			End Select
		End Select
	End Select
End Function
