gt: 			return (Map<Object, Object>) obj;
context: package sk.upjs.paz.graph.visualization;
  
  import javax.swing.*;
  
  import java.util.*;
  
  import java.awt.BorderLayout;
  import java.awt.Color;
  import java.awt.Component;
  import java.awt.Dimension;
  import java.awt.event.ActionListener;
  import java.awt.event.ActionEvent;
  
  import javax.swing.border.EmptyBorder;
  import javax.swing.border.BevelBorder;
  import javax.swing.GroupLayout.Alignment;
  import javax.swing.LayoutStyle.ComponentPlacement;
  import javax.swing.Timer;
  import javax.swing.table.AbstractTableModel;
  import javax.swing.table.DefaultTableCellRenderer;
  
  import sk.upjs.paz.graph.*;
  
  import java.lang.reflect.Array;
  import java.util.concurrent.Semaphore;
  
  /**
   * The frame displaying all visualization components.
   */
  @SuppressWarnings("serial")
  class GraphFrame extends JFrame {
  
  	// -----------------------------------------------------------------------------------
  	// -----------------------------------------------------------------------------------
  	// MonitoredObject
  	// -----------------------------------------------------------------------------------
  	// -----------------------------------------------------------------------------------
  
  	/**
  	 * Represents a monitored object.
  	 */
  	private static class MonitoredObject {
  		/**
  		 * Name of the monitored object
  		 */
  		String name;
  
  		/**
  		 * Monitored object.
  		 */
  		Object monitoredObject;
  
  		@Override
  		public String toString() {
  			if (name != null)
  				return name;
  			else
  				return monitoredObject.toString();
  		}
  	}
  
  	// -----------------------------------------------------------------------------------
  	// -----------------------------------------------------------------------------------
  	// KeyValueTableModel
  	// -----------------------------------------------------------------------------------
  	// -----------------------------------------------------------------------------------
  
  	/**
  	 * Table model for displaying key-value collection of monitored object.
  	 */
  	private static class KeyValueTableModel extends AbstractTableModel {
  		/**
  		 * Key value pairs.
  		 */
  		private final Map<Object, Object> valuesMap = new HashMap<Object, Object>();
  
  		/**
  		 * List containing ordered keys.
  		 */
  		private final List<Object> keysOrder = new ArrayList<Object>();
  
  		/**
  		 * Keys for which the value was changed.
  		 */
  		private final Set<Object> changedKeys = new HashSet<Object>();
  
  		/**
  		 * Clear the table.
  		 */
  		public void clear() {
  			valuesMap.clear();
  			keysOrder.clear();
  			fireTableDataChanged();
  		}
  
  		/**
  		 * Set new content of the table.
  		 */
  		public void updateContent(Map<Object, Object> rows, boolean displayChanges) {
  			Map<Object, Object> compareMap = null;
  			boolean noChangeFound = true;
  			if (displayChanges)
  				compareMap = new HashMap<Object, Object>(valuesMap);
  			else
  				changedKeys.clear();
  
  			valuesMap.clear();
  			keysOrder.clear();
  			for (Map.Entry<Object, Object> entry : rows.entrySet()) {
  
  				// if check for changes is enabled
  				if (displayChanges) {
  					Object oldValue = compareMap.get(entry.getKey());
  					boolean changed;
  					if (oldValue == null) {
  						changed = (oldValue != entry.getValue());
  					} else {
  						changed = !(oldValue.equals(entry.getValue()));
  					}
  
  					if (changed) {
  						if (noChangeFound) {
  							noChangeFound = false;
  							changedKeys.clear();
  						}
  
  						changedKeys.add(entry.getKey());
  					}
  				}
  
  				valuesMap.put(entry.getKey(), entry.getValue());
  				keysOrder.add(entry.getKey());
  			}
  
  			// if display of changes is enabled and there was no change
  			// detected, we end without firing of data changes.
  			if (displayChanges && noChangeFound)
  				return;
  
  			fireTableDataChanged();
  		}
  
  		@Override
  		public int getColumnCount() {
  			return 2;
  		}
  
  		@Override
  		public String getColumnName(int column) {
  			if (column == 0)
  				return "Key";
  			else
  				return "Value";
  		}
  
  		@Override
  		public Class<?> getColumnClass(int columnIndex) {
  			if (columnIndex == 0)
  				return String.class;
  			else
  				return ColoredText.class;
  		}
  
  		@Override
  		public int getRowCount() {
  			return valuesMap.size();
  		}
  
  		@Override
  		public Object getValueAt(int row, int collumn) {
  			if ((row >= 0) && (row < valuesMap.size())) {
  				if (collumn == 0)
  					return keysOrder.get(row);
  				else {
  					Object key = keysOrder.get(row);
  					return new ColoredText(valuesMap.get(key), changedKeys.contains(key) ? Color.yellow : Color.white);
  				}
  			}
  
  			return null;
  		}
  
  		/**
  		 * Clean changes.
  		 */
  		public void clearChanges() {
  			changedKeys.clear();
  			fireTableDataChanged();
  		}
  	}
  
  	// -----------------------------------------------------------------------------------
  	// -----------------------------------------------------------------------------------
  	// Label
  	// -----------------------------------------------------------------------------------
  	// -----------------------------------------------------------------------------------
  
  	/**
  	 * Named label.
  	 */
  	private static class Label {
  		String name;
  
  		/**
  		 * Constructs a new label with given name.
  		 * 
  		 * @param name
  		 *            the name of label.
  		 */
  		public Label(String name) {
  			this.name = name;
  		}
  
  		@Override
  		public int hashCode() {
  			final int prime = 31;
  			int result = 1;
  			result = prime * result + ((name == null) ? 0 : name.hashCode());
  			return result;
  		}
  
  		@Override
  		public boolean equals(Object obj) {
  			if (this == obj)
  				return true;
  			if (obj == null)
  				return false;
  			if (getClass() != obj.getClass())
  				return false;
  			Label other = (Label) obj;
  			if (name == null) {
  				if (other.name != null)
  					return false;
  			} else if (!name.equals(other.name))
  				return false;
  			return true;
  		}
  
  		@Override
  		public String toString() {
  			return name.toString();
  		}
  	}
  
  	// -----------------------------------------------------------------------------------
  	// -----------------------------------------------------------------------------------
  	// Cell rendering
  	// -----------------------------------------------------------------------------------
  	// -----------------------------------------------------------------------------------
  
  	private static class ColoredTextRenderer extends DefaultTableCellRenderer {
  		public ColoredTextRenderer() {
  			super();
  		}
  
  		@Override
  		public Component getTableCellRendererComponent(JTable table, Object value, boolean isSelected, boolean hasFocus,
  				int row, int column) {
  			Component result = super.getTableCellRendererComponent(table, value, isSelected, hasFocus, row, column);
  			if (!isSelected) {
  				if ((value != null) && (value instanceof ColoredText)) {
  					result.setBackground(((ColoredText) value).color);
  				}
  			}
  			return result;
  		}
  	}
  
  	/**
  	 * Special class for highlighted values.
  	 */
  	private static class ColoredText {
  		private Object obj;
  		private Color color;
  
  		public ColoredText(Object obj, Color color) {
  			this.obj = obj;
  			this.color = color;
  		}
  
  		@Override
  		public String toString() {
  			if (obj != null)
  				return obj.toString();
  			else
  				return "";
  		}
  	}
  
  	// -----------------------------------------------------------------------------------
  	// -----------------------------------------------------------------------------------
  	// Breakpoint (pause)
  	// -----------------------------------------------------------------------------------
  	// -----------------------------------------------------------------------------------
  
  	/**
  	 * The breakpoint that stops execution of an thread executing an algorithm.
  	 */
  	private static class Breakpoint {
  		/**
  		 * Semaphore that block the thread executing an algorithm.
  		 */
  		Semaphore semaphore;
  
  		/**
  		 * Description of the breakpoint.
  		 */
  		String description;
  	}
  
  	// -----------------------------------------------------------------------------------
  	// -----------------------------------------------------------------------------------
  	// Instance variables
  	// -----------------------------------------------------------------------------------
  	// -----------------------------------------------------------------------------------
  
  	/**
  	 * Graph that is visualized in this frame.
  	 */
  	private Graph graph;
  
  	/**
  	 * List of monitored objects
  	 */
  	private final List<MonitoredObject> monitoredObjects = new ArrayList<MonitoredObject>();
  
  	/**
  	 * Special record for monitored object that is always monitoring selected
  	 * graph object.
  	 */
  	private final MonitoredObject graphObjectSelection = new MonitoredObject();
  
  	/**
  	 * Currently actively monitored object.
  	 */
  	private MonitoredObject monitorSelection;
  
  	/**
  	 * Table model for displaying key-value table of actively monitored object.
  	 */
  	private final KeyValueTableModel mapTableModel = new KeyValueTableModel();
  
  	/**
  	 * Queue of unconfirmed semaphores.
  	 */
  	private final Queue<Breakpoint> breakpoints = new LinkedList<Breakpoint>();
  
  	/**
  	 * The graph panel displaying the visualized graph.
  	 */
  	private GraphPanel graphPanel;
  
  	/**
  	 * Combobox with list of objects that are monitored.
  	 */
  	private JComboBox<MonitoredObject> mapComboBox;
  
  	/**
  	 * Checkbox for enabling/disabling display of weights of graph edges.
  	 */
  	private JCheckBox showWeightsCheckbox;
  
  	/**
  	 * Table displaying key-value pairs of the monitored object.
  	 */
  	private JTable mapTable;
  
  	/**
  	 * Button to control visualization breakpoints.
  	 */
  	private JButton continueButton;
  
  	/**
  	 * Label for displaying the title of the current breakpoint (for instance
  	 * the title can be description of the current state of the algorithm
  	 * execution).
  	 */
  	private JLabel breakpointTitleLabel;
  
  	/**
  	 * Timer that control refresh of the monitored object.
  	 */
  	private javax.swing.Timer refreshTimer;
  
  	/**
  	 * Period of refresh of the monitored object.
  	 */
  	private static final int MONITOR_REFRESH_PERIOD = 1000;
  
  	// -----------------------------------------------------------------------------------
  	// -----------------------------------------------------------------------------------
  	// Constructors
  	// -----------------------------------------------------------------------------------
  	// -----------------------------------------------------------------------------------
  
  	/**
  	 * Constructs the frame.
  	 */
  	public GraphFrame() {
  		this(null);
  	}
  
  	/**
  	 * Constructs a graph visualization frame.
  	 * 
  	 * @param graph
  	 *            the graph that is visualized.
  	 */
  	public GraphFrame(Graph graph) {
  		this.graph = graph;
  		initializeComponents();
  
  		// create default monitored object - properties of a selected graph
  		// object
  		graphObjectSelection.name = "Selected object";
  		monitoredObjects.add(graphObjectSelection);
  		updateListOfMonitoredObjects();
  		onMonitorChanged();
  
  		installRefreshTimer();
  	}
  
  	// -----------------------------------------------------------------------------------
  	// -----------------------------------------------------------------------------------
  	// Custom visualization colors
  	// -----------------------------------------------------------------------------------
  	// -----------------------------------------------------------------------------------
  
  	/**
  	 * Sets visualization color for an object of a graph (vertex or edge).
  	 * 
  	 * @param obj
  	 *            the graph object.
  	 * @param color
  	 *            the desired visualization color.
  	 */
  	public void setVisualizationColor(Object obj, Color color) {
  		graphPanel.setVisualizationColor(obj, color);
  	}
  
  	/**
  	 * Resets visualization color of all parts of the graph.
  	 */
  	public void resetAllColors() {
  		graphPanel.resetAllColors();
  	}
  
  	// -----------------------------------------------------------------------------------
  	// -----------------------------------------------------------------------------------
  	// Monitoring
  	// -----------------------------------------------------------------------------------
  	// -----------------------------------------------------------------------------------
  
  	/**
  	 * Adds a new object to the set of monitored objects.
  	 * 
  	 * @param name
  	 *            the displayed name of the monitored object.
  	 * @param monitoredObject
  	 *            the monitored object.
  	 */
  	public void addToMonitor(String name, Object monitoredObject) {
  		if (monitoredObject == null)
  			return;
  
  		if (name != null)
  			name = name.trim();
  
  		boolean found = false;
  		for (MonitoredObject mo : monitoredObjects) {
  			if (mo.monitoredObject == monitoredObject) {
  				mo.name = name;
  				found = true;
  				break;
  			}
  		}
  
  		if (!found) {
  			MonitoredObject mo = new MonitoredObject();
  			mo.name = name;
  			mo.monitoredObject = monitoredObject;
  			monitoredObjects.add(mo);
  		}
  
  		updateListOfMonitoredObjects();
  	}
  
  	/**
  	 * Removes a monitored object from the set of monitored objects.
  	 * 
  	 * @param monitoredObject
  	 *            the monitored object to be removed from monitoring.
  	 */
  	public void removeFromMonitor(Object monitoredObject) {
  		boolean wasChange = false;
  		Iterator<MonitoredObject> it = monitoredObjects.iterator();
  		while (it.hasNext()) {
  			MonitoredObject mo = it.next();
  			if (mo.monitoredObject == monitoredObject) {
  				it.remove();
  				wasChange = true;
  				break;
  			}
  		}
  
  		if (wasChange)
  			updateListOfMonitoredObjects();
  	}
  
  	/**
  	 * Updates combobox for choosing actively monitored object.
  	 */
  	private void updateListOfMonitoredObjects() {
  		MonitoredObject oldSelection = monitorSelection;
  		mapComboBox
  				.setModel(new DefaultComboBoxModel<MonitoredObject>(monitoredObjects.toArray(new MonitoredObject[0])));
  
  		monitorSelection = (MonitoredObject) mapComboBox.getSelectedItem();
  		if (monitorSelection != oldSelection)
  			onMonitorChanged();
  	}
  
  	/**
  	 * Realizes all actions after changing which object is monitored.
  	 */
  	private void onMonitorChanged() {
  		monitorSelection = (MonitoredObject) mapComboBox.getSelectedItem();
  		if (monitorSelection != null) {
  			mapTableModel.updateContent(transformToMap(monitorSelection.monitoredObject), false);
  		} else {
  			mapTableModel.clear();
  		}
  	}
  
  	/**
  	 * Transforms the state of a object to a map, i.e., a set of key-value
  	 * pairs.
  	 * 
  	 * @param obj
  	 *            the object to be transformed to a map.
  	 * @return the map describing the object or empty map, if the object cannot
  	 *         be transformed to the map.
  	 */
  	@SuppressWarnings("unchecked")
  	private Map<Object, Object> transformToMap(Object obj) {
  		if (obj == null)
  			return Collections.emptyMap();
  
  		// Map
  		if (obj instanceof Map) {
  