/* -*- tab-width: 4 -*-
*
* Electric(tm) VLSI Design System
*
* File: EditWindowFocusBrowser.java
*
* Copyright (c) 2005 Sun Microsystems and Static Free Software
*
* Electric(tm) is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 3 of the License, or
* (at your option) any later version.
*
* Electric(tm) is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with Electric(tm); see the file COPYING. If not, write to
* the Free Software Foundation, Inc., 59 Temple Place, Suite 330,
* Boston, Mass 02111-1307, USA.
*/
package com.sun.electric.tool.user.ui;
import java.awt.geom.Point2D;
import java.util.ArrayList;
import java.util.List;
/**
* This class saves foci much like a web browser saves page history.
* A focus is a particular zoom and pan location of a cell in an EditWindow.
* The browser saves old foci, and lets you move
* forward and backward between them. When a new focus is created,
* all foci forward of the current one are destroyed, much like typing
* in a new URL into a web browser.
*/
public class EditWindowFocusBrowser {
// The associated EditWindow whose foci we will remember
private EditWindow editWindow;
// The list of saved foci
private List<Focus> savedFoci;
// A pointer to the current focus (which is saved)
private int currentFocus;
// flag to check if call to updateCurrentFocus was the first
// call since the last save
private boolean firstUpdate;
// maximum number of saved foci
private static final int MAXSAVEDFOCI = 10;
private static final boolean DEBUG = false;
private static class Focus {
private final Point2D offset;
private final double scale;
private Focus(Point2D offset, double scale) {
this.offset = offset;
this.scale = scale;
}
public String toString() {
return "offset="+offset.getX()+","+offset.getY()+" scale="+scale;
}
}
/**
* Create a new Focus Browser associated with the given EditWindow
* @param controller
*/
EditWindowFocusBrowser(EditWindow controller) {
this.editWindow = controller;
savedFoci = new ArrayList<Focus>();
clear();
}
/**
* Go back to the last saved focus
*/
public void goBack() {
int previousFocus = currentFocus-1;
if (previousFocus < 0) {
System.out.println("No more previous focus history");
return;
}
if (previousFocus >= savedFoci.size()) return;
// first update current focus
updateCurrentFocus();
// go to previous focus
Focus focus = savedFoci.get(previousFocus);
restoreFocus(focus);
currentFocus = previousFocus;
if (DEBUG) System.out.println("Went back, last saved focus is "+currentFocus+" out of "+savedFoci.size());
}
/**
* Go forward to the next saved focus
*/
public void goForward() {
if (currentFocus < 0) return;
int nextFocus = currentFocus+1;
if (nextFocus >= savedFoci.size()) {
System.out.println("No more forward focus history");
return;
}
// first update current focus
updateCurrentFocus();
// go to next focus
Focus focus = savedFoci.get(nextFocus);
restoreFocus(focus);
currentFocus = nextFocus;
if (DEBUG) System.out.println("Went forward, last saved focus is "+currentFocus+" out of "+savedFoci.size());
}
/**
* Restore the edit window to the given focus
* @param focus
*/
private void restoreFocus(Focus focus) {
editWindow.setOffset(focus.offset);
editWindow.setScale(focus.scale);
editWindow.fullRepaint();
if (DEBUG) System.out.println("restored focus "+focus);
}
/**
* Save the current focus. Note that this destroys all
* foci forward of the last saved focus.
*/
void saveCurrentFocus() {
saveCurrentFocusNoUpdateClear();
firstUpdate = true;
}
// separate method for internal use that does not clear firstUpdate flag
private void saveCurrentFocusNoUpdateClear() {
Focus focus = new Focus(editWindow.getOffset(), editWindow.getScale());
// delete foci forward of this focus
while (currentFocus < savedFoci.size()-1) {
if (savedFoci.size() == 0) break;
savedFoci.remove(savedFoci.size()-1);
if (DEBUG) System.out.println("removed old focus "+(savedFoci.size()-1));
}
savedFoci.add(focus);
currentFocus++;
if (DEBUG) System.out.println("Added new saved focus as "+currentFocus+" out of "+savedFoci.size());
if (DEBUG) System.out.println("saved focus "+focus);
// remove old ones if we are over the limit
if (currentFocus > MAXSAVEDFOCI) {
savedFoci.remove(0);
currentFocus--;
}
}
/**
* Clear all saved foci
*/
void clear() {
currentFocus = -1; // no current focus
savedFoci.clear();
firstUpdate = true;
}
/**
* Updates the current focus with any changes to panning
*/
public void updateCurrentFocus() {
if (currentFocus < 0) return;
if (currentFocus >= savedFoci.size()) return;
if (firstUpdate) {
// save current focus as a new focus
// call special function that won't reset firstUpdate flag
saveCurrentFocusNoUpdateClear();
firstUpdate = false;
return;
}
// otherwise, we just update the current focus
Focus focus = new Focus(editWindow.getOffset(), editWindow.getScale());
savedFoci.set(currentFocus, focus);
}
}