Increase the font size of the label column in an AlarmStatusTable in Vision

I remember briefly looking at this problem here:

...but unfortunately, at the time, I didn't know how to do it, and based on my current understanding, I don't believe that the alarm status table's row styler can be conventionally overridden with ignition's stock flavor of Jython.

That said, I've been developing a way to add user defined columns to the alarm status table, and although this development is not complete, the approach I'm using actually makes your usage case rather simple.

What I'm doing is pulling the tableModel out of the main jidetable along with all of its relevant listeners, and I'm using them to configure a stock jtable, which I subsequently insert into the viewport in place of the original table. Afterwards, I simply script everything that is lost or broken in the process: the sortable table header, the header popup menu, the row styling, etc.

By doing this, I am able to use prepareRenderer to program the custom row styling, which in practice, looks a lot like the configureCell extension function in the power table. For your usage case, I added a condition to increase the label column font, and it worked perfectly. The only thing I had to do additionally was add a method for updating the checkbox row height because the checkmarks live in a separate table that does not inherently have a listener for custom font sizes. Here is result:

As you can see in the video, I have thoroughly tested this approach, and everything works as expected. To test this in a designer, you can simply fire the script using a button, but for this to work seamlessly in an actual session, the script will need to be fired from the parent window's internalFrameOpened event handler. The code I'm posting is already set up for both from where I've done my own session testing; just move the hash mark from the second line of code to the first line of code to configure this for session use. Obviously, if your alarm status table has a unique name or is nested in a container of some kind, the path will need to be changed accordingly.

Here is the code:

alarmStatusTable = event.source.parent.getComponent('Alarm Status Table') #From a Test Button in the same container as the alarm status table
#alarmStatusTable = system.gui.getParentWindow(event).getComponentForPath('Root Container.Alarm Status Table') #From the parent window's internalFrameOpened event handler

from javax.swing import JTable, JPopupMenu, JMenuItem, JCheckBoxMenuItem
from javax.swing.table import TableColumn
from java.awt import Color, Font
from java.awt.event import MouseAdapter
from java.awt.event import MouseEvent
from com.jidesoft.grid import JideTable, TableHeaderPopupMenuInstaller
labelFont = Font('Arial', Font.BOLD, 20)
selectedColumn = None
class ModifiedTable(JTable):#Styles the jtable
	def prepareRenderer(self, renderer, row, column):
		component = super(ModifiedTable, self).prepareRenderer(renderer, row, column)
		value = self.getValueAt(row, column)
		component.setForeground(Color.white)
		if str(self.getModel().getValueAt(row, 16)) == 'Diagnostic':
			component.setBackground(Color(128,128,128))
		elif str(self.getModel().getValueAt(row, 18)) == 'Active, Unacknowledged' and str(self.getModel().getValueAt(row, 16)) == 'Critical':
			component.setBackground(Color(255,0,0))
		elif str(self.getModel().getValueAt(row, 18)) == 'Active, Unacknowledged':
			component.setBackground(Color(255,255,0))
			component.setForeground(Color(0,0,0))
		elif str(self.getModel().getValueAt(row, 18)) == 'Active, Acknowledged':
			component.setBackground(Color(174,0,0))
		elif str(self.getModel().getValueAt(row, 18)) == 'Cleared, Unacknowledged':
			component.setBackground(Color(0,174,174))
		elif str(self.getModel().getValueAt(row, 18)) == 'Cleared, Acknowledged':
			component.setBackground(Color(128,128,128))
		if self.getColumnName(column) == 'Label':
			component.setFont(labelFont)
		return component
def hideColumnActionPerformed(event):#Hides selected column when header popup menu option is cicked
	table = getTable(alarmStatusTable)
	columnModel = table.getColumnModel()
	tableColumn = columnModel.getColumn(selectedColumn)
	table.getColumnModel().removeColumn(tableColumn)
def showAllActionPerformed(event):
	table = getTable(alarmStatusTable)
	tableModel = table.getModel()
	tableModel.fireTableStructureChanged()
def checkBoxActionPerformed(event, index):#Adds or removes columns when checkboxes are clicked in the header popup menu
	table = getTable(alarmStatusTable)
	columns = getColumns(table, True)
	modelIndex = int(str(event.source.name)[8:])
	columnModel = table.getColumnModel()
	columnCount = table.columnCount
	if event.source.isSelected():
		tableHeaders= table.getTableHeader()
		columnModel.addColumn(TableColumn(modelIndex))
		tableColumn = columnModel.getColumn(table.columnCount-1)
		tableColumn.setHeaderValue(columns[modelIndex])
		tableHeaders.repaint()
	else:
		for column in range(columnCount):
			columnIndex = (columnCount-1)-column
			if table.convertColumnIndexToModel(columnIndex) == modelIndex:
				tableColumn = columnModel.getColumn(columnIndex)
				columnModel.removeColumn(tableColumn)
class PopupMouseListener(MouseAdapter):#Header mouse click listenser
    def mousePressed(self, event):
		global selectedColumn
		selectedColumn = table.columnAtPoint(event.getPoint())
		if event.getButton() == MouseEvent.BUTTON3:#Creates popup menu if right mouse button is clicked from the table header
			allColumns = getColumns(table, True)
			tableColumns = getColumns(table, False)
			popupMenu = JPopupMenu()
			hideColumnSelection = JMenuItem("Hide This Column")
			hideColumnSelection.addActionListener(hideColumnActionPerformed)
			showAllColumnsSelection = JMenuItem("Show All Columns")
			showAllColumnsSelection.addActionListener(showAllActionPerformed)
			popupMenu.add(hideColumnSelection)
			popupMenu.add(showAllColumnsSelection)	
			popupMenu.addSeparator()
			for index, column in enumerate(allColumns):
				checkbox = JCheckBoxMenuItem(column)
				checkbox.name = 'checkbox' + str(index).zfill(2)
				if checkbox.text in tableColumns:
					checkbox.setSelected(True)
				else:
					checkbox.setSelected(False)
				checkbox.addActionListener(lambda event: checkBoxActionPerformed(event, index))
				popupMenu.add(checkbox)
			table.getTableHeader().setComponentPopupMenu(popupMenu)
			popup = table.getTableHeader().getComponentPopupMenu()
			popup.show(event.getComponent(), event.getX(), event.getY())
		elif event.getClickCount() == 2:#Sorts, reverse sorts, or unsorts column if column header is double clicked
			tableModel = table.getModel()
			modelIndex = table.convertColumnIndexToModel(selectedColumn)
			if not table.getModel().isColumnSorted(modelIndex):
				for column in range(table.columnCount):
					tableModel.unsortColumn(table.convertColumnIndexToModel(column))
				tableModel.sortColumn(modelIndex)
			elif tableModel.isColumnAscending(modelIndex):
				tableModel.reverseColumnSortOrder(modelIndex)
			else:
				tableModel.unsortColumn(modelIndex)
def alignCheckboxes(alarmStatusTable, table):#Makes checkbox table and main table row height the same after font adjusment, so the rows still line up
	if alarmStatusTable.componentCount > 0:
			for component in alarmStatusTable.getComponents():
				if isinstance(component, JideTable):
					component.setRowHeight(table.getRowHeight())
					break
				alignCheckboxes(component, table)
def getColumns(table, getAll):#retrieves a list of column names from the table or table model depending on if getAll is True or not
	columnList = []
	if getAll:
		for column in range(table.getModel().columnCount):
		    columnList.append(table.getModel().getColumnName(column))
		return(columnList)
	else:
		for column in range(table.columnCount):
			columnList.append(table.getColumnName(column))
		return columnList
def getTable(alarmStatusTable):#Retrieves a fresh jTable instance from the alarmStatusTable
	if alarmStatusTable.componentCount > 0:
		for component in alarmStatusTable.getComponents():
			if 'AlarmStatusTable$1' in str(component.__class__):
				originalTable = component
				columnList = getColumns(originalTable, False)
				tableModelField = originalTable.getClass().getSuperclass().getDeclaredField('Cc')
				tableModelField.setAccessible(True)
				tableModel = tableModelField.get(originalTable)
				table = ModifiedTable(tableModel)
				listener = component.getSortableHeaderMouseListener()
				viewport = originalTable.getParent()
				viewport.add(table)
				table.addMouseListener(listener)
				table.getTableHeader().addMouseListener(PopupMouseListener())
				popupInstaller = TableHeaderPopupMenuInstaller(table)
				popupInstaller.installListeners()
				columnModel = table.getColumnModel()
				columnCount = table.columnCount
				for column in range(columnCount):
					columnIndex = (columnCount-1)-column
					if table.getColumnName(columnIndex) not in columnList:
						tableColumn = columnModel.getColumn(columnIndex)
						columnModel.removeColumn(tableColumn)
				return table
			elif 'ModifiedTable' in str(component.__class__):
				return component
			else:
				result = getTable(component)
				if result is not None:
					return result
	return None
table = getTable(alarmStatusTable)
alignCheckboxes(alarmStatusTable, table)
2 Likes