private static <T> void doWaitForTableModel(ThreadedTableModel<T, ?> model) {

		// Always wait for Swing at least once.  There seems to be a race condition for
		// incremental threaded models where the table is not busy at the time this method
		// is called, but there is an update pending via an invokeLater().
		waitForSwing();

		boolean didWait = false;
		int waitTime = 0;
		while (model.isBusy()) {
			didWait = true;
			waitTime += sleep(DEFAULT_WAIT_DELAY);

			// model loading may take longer than normal waits
			if (waitTime >= PRIVATE_LONG_WAIT_TIMEOUT) {
				Msg.error(AbstractDockingTest.class, createStackTraceForAllThreads()); // debug				
				String busyState = getBusyState(model);
				Msg.error(AbstractDockingTest.class, busyState);
				throw new AssertException(
					"Timed-out waiting for table model to load in " + waitTime + "ms");
			}
		}

		waitForSwing();

		if (didWait) {
			// try again (the idea is that we may have had a small window where the model was
			// not busy, but more work may be pushed on)
			waitForTableModel(model);
		}
	}
Returns a pretty-print string of all found windows that are showing, nesting by
parent-child relationship.

@return the result string
Ghidra/Framework/Docking/src/main/java/docking/test/AbstractDockingTest.java