package org.xmind.ui.internal.mindmap; import java.io.BufferedWriter; import java.io.File; import java.io.FileInputStream; import java.io.FileOutputStream; import java.io.IOException; import java.io.InputStreamReader; import java.io.OutputStreamWriter; import java.io.Writer; import java.lang.reflect.Field; import java.net.URI; import org.eclipse.swt.widgets.Display; import org.eclipse.ui.IMemento; import org.eclipse.ui.XMLMemento; import org.w3c.dom.Element; import org.w3c.dom.Node; import org.w3c.dom.NodeList; import org.xmind.core.ISheet; import org.xmind.core.IWorkbook; import org.xmind.gef.ui.editor.IGraphicalEditorPage; import org.xmind.ui.internal.MindMapUIPlugin; import org.xmind.ui.mindmap.IWorkbookRef; import org.xmind.ui.prefs.PrefConstants; import org.xmind.ui.util.MindMapUtils; public class MindMapState { private static final String TAG_STATES = "states"; //$NON-NLS-1$ private static final String TAG_WORKBOOK = "workbook"; //$NON-NLS-1$ private static final String TAG_SHEET = "sheet"; //$NON-NLS-1$ private static final String TAG_STATE_ZOOM = "zoom"; //$NON-NLS-1$ private static final String STATE_FILE = "/state.xml"; //$NON-NLS-1$ private static final String ZOOM_VALUE = "zoom-value"; //$NON-NLS-1$ private static final int NEGATIVE_INDEX = -1; private volatile static MindMapState instance; private static final int MAX_STATE_NUM = 100; private File stateFile; private XMLMemento root; private MindMapState() { init(); } private void init() { if (root == null) { root = getRootMemento(); } } public void saveState(IWorkbookRef workbookRef, IGraphicalEditorPage[] pages) { if (workbookRef != null) { IWorkbook workbook = workbookRef.getWorkbook(); URI uri = workbookRef.getURI(); if (workbook != null && uri != null) { if (pages != null && !(pages.length == 0)) { for (IGraphicalEditorPage page : pages) writeState(page, uri); } } } } private void writeState(IGraphicalEditorPage page, URI uri) { try { ISheet sheet = MindMapUtils.findSheet(page); int workbookIndex = getWorkbookIndex(root.getChildren(TAG_WORKBOOK), uri.toString()); if (workbookIndex != NEGATIVE_INDEX) { IMemento workbookMem = root .getChildren(TAG_WORKBOOK)[workbookIndex]; int index = getSheetIndex(workbookMem.getChildren(TAG_SHEET), sheet.getId()); if (index != NEGATIVE_INDEX) { IMemento sheetMem = workbookMem .getChildren(TAG_SHEET)[index]; IMemento zoomMem = sheetMem.getChild(TAG_STATE_ZOOM); setZoomValue(page, zoomMem); } else { IMemento zoomMem = createZoomMem(sheet, workbookMem); setZoomValue(page, zoomMem); } } else { if (root.getChildren(TAG_WORKBOOK).length >= MAX_STATE_NUM) { removeOldestState(); } IMemento workbookMem = root.createChild(TAG_WORKBOOK, uri.toString()); IMemento zoomMem = createZoomMem(sheet, workbookMem); setZoomValue(page, zoomMem); } File sf = getStateFile(); Writer writer = new BufferedWriter( new OutputStreamWriter(new FileOutputStream(sf), "utf-8"), //$NON-NLS-1$ 1024); try { root.save(writer); } finally { writer.close(); } } catch (Exception e) { } } private void removeOldestState() { try { Field eleField = root.getClass().getDeclaredField("element"); //$NON-NLS-1$ boolean isAccessible = eleField.isAccessible(); eleField.setAccessible(true); Element element = (Element) eleField.get(root); NodeList list = element.getElementsByTagName(TAG_WORKBOOK); if (list != null && list.getLength() > 0) { Node firstWorkbookNode = list.item(0); element.removeChild(firstWorkbookNode); } eleField.setAccessible(isAccessible); } catch (NoSuchFieldException e) { e.printStackTrace(); } catch (SecurityException e) { e.printStackTrace(); } catch (IllegalArgumentException e) { e.printStackTrace(); } catch (IllegalAccessException e) { e.printStackTrace(); } } private IMemento createZoomMem(ISheet sheet, IMemento workbookMem) { IMemento sheetMem = workbookMem.createChild(TAG_SHEET, sheet.getId()); IMemento zoomMem = sheetMem.createChild(TAG_STATE_ZOOM); return zoomMem; } private void setZoomValue(IGraphicalEditorPage page, IMemento zoomMem) { zoomMem.putFloat(ZOOM_VALUE, (float) page.getViewer().getZoomManager().getScale()); } public void loadState(IWorkbookRef workbookRef, IGraphicalEditorPage page) { URI uri = workbookRef.getURI(); if (uri == null) return; ISheet sheet = MindMapUtils.findSheet(page); boolean hasZoom = false; int workbookIndex = getWorkbookIndex(root.getChildren(), uri.toString()); if (workbookIndex != NEGATIVE_INDEX) { IMemento workbookMem = root .getChildren(TAG_WORKBOOK)[workbookIndex]; int index = getSheetIndex(workbookMem.getChildren(TAG_SHEET), sheet.getId()); if (index != NEGATIVE_INDEX) { hasZoom = true; IMemento sheetMem = workbookMem.getChildren(TAG_SHEET)[index]; IMemento zoomMem = sheetMem.getChild(TAG_STATE_ZOOM); Float zoom = zoomMem.getFloat(ZOOM_VALUE); page.getViewer().getZoomManager().setScale(zoom); } } if (!hasZoom) { int zoom = MindMapUIPlugin.getDefault().getPreferenceStore() .getInt(PrefConstants.ZOOM_VALUE); if (zoom != 0) { page.getViewer().getZoomManager().setScale(zoom / 100d); hasZoom = true; } } if (!hasZoom) { int width = Display.getCurrent().getBounds().width; if (1366 <= width && width <= 1920) page.getViewer().getZoomManager().setScale(1.2d); else if (width > 1920) page.getViewer().getZoomManager().setScale(1.5d); } } private File getStateFile() { if (stateFile == null) stateFile = new File( MindMapUIPlugin.getDefault().getStateLocation().toFile(), STATE_FILE); return stateFile; } private int getSheetIndex(IMemento[] children, String id) { int index = 0; for (IMemento mem : children) { if (id.equals(mem.getID())) return index; index++; } return NEGATIVE_INDEX; } private int getWorkbookIndex(IMemento[] children, String file) { int index = 0; for (IMemento mem : children) { if (mem.getID().equals(file)) return index; index++; } return NEGATIVE_INDEX; } private XMLMemento getRootMemento() { XMLMemento memento = null; InputStreamReader reader = null; try { File sf = getStateFile(); reader = new InputStreamReader(new FileInputStream(sf), "utf-8"); //$NON-NLS-1$ memento = XMLMemento.createReadRoot(reader); } catch (Exception e) { } finally { if (reader != null) { try { reader.close(); } catch (IOException e2) { } } } if (memento == null) { memento = XMLMemento.createWriteRoot(TAG_STATES); } return memento; } public static MindMapState getInstance() { if (instance == null) { synchronized (MindMapState.class) { if (instance == null) { instance = new MindMapState(); } } } return instance; } }