The scenerio is that I have different type of drawing components on drawing area. In menu I have some combo boxes which apply different properties on these objects. and also add a new UndoableEdit to the UndoManager. Anybody worked with the swing's undo package will get the idea. This way I am successfully performing undo and redo functionality. But the problem is in many cases I need to update the state of these combo boxes for example when a new object is added, appropriate value in the combo boxes has to be selected or when user selects another object, I update the selected index of the combo boxes. On calling the setSelectedIndex() function of these combo boxes the actionPerformed method of the combobox is automatically called which also adds a new undoableEdit into the UndoManager which is not desired since user has not performed any action on the combobox to update the property but I dynamically updated the state of the combobox to match it with the currently selected object. Anybody has solution to this problem?

I had the same problem and could not find a good approach to handle this (anyone did?).
My workaround to the problem was to filter the setXXX calls caused by focus changes based on a timestamp.
My code customized UndoManager class' code looks like this:

/**
 * Time of last undoable edit<p>
 * We use this as a workaround when undoing in the following case:<br>
 * - table cell was edited and <br>
 * - undo toolbar-button clicked<br>
 * this causes a stopEdit which in turn causes setValueAt and produces a new edit.<br>
 * If the last edit was created less then MINTIME far (ex. 0.2sec), we undo twice.
 */
private GregorianCalendar editTime;


public synchronized boolean addEdit(UndoableEdit anEdit) {
	this.editTime = new GregorianCalendar();
    editTime.add(Calendar.MILLISECOND, MIN_TIME);	// only after this time, an  xxxxxxxxxx
    boolean success = super.addEdit(anEdit);
    if (success) {
    	adjustMenuState();
    }
	return success;
}

@Override
public synchronized void undo()  {
  try
    {
	  // filter out unwanted edits from focus changes
	  if(editTime.after(GregorianCalendar.getInstance())){
		  	// timeout this one so we can undo it
        	editTime.set(Calendar.YEAR, 1900);	
        	// undo it and kill the unwanted one
        	UndoableEdit e = this.editToBeUndone();
        	undo();	// undo the unwanted
        	if(e instanceof TableCellEdit) {
        		TableCellEdit tce = (TableCellEdit) e;
        		log.warn("Remove edit :" +tce.getPresentationName() + ", " + tce.toString());
        	}
        	e.die();	
        }
	  	// do the undo
        super.undo();
    }
    finally
    {
    	// will call undoTo adjustMenuState();
    }
}

I posted a full description of the Java Undo/Redo mechanism in my blog SNIPPED (without the timestamp mechanism).

Be a part of the DaniWeb community

We're a friendly, industry-focused community of developers, IT pros, digital marketers, and technology enthusiasts meeting, networking, learning, and sharing knowledge.