From 97bdef994255b1f70b248d784a69a6f874e8596e Mon Sep 17 00:00:00 2001 From: Phillipus Date: Mon, 20 Jan 2025 12:39:30 +0000 Subject: [PATCH] Refactor TreeStateHelper - Improved readability and optimised --- .../editor/views/tree/TreeStateHelper.java | 146 +++++++++--------- 1 file changed, 75 insertions(+), 71 deletions(-) diff --git a/com.archimatetool.editor/src/com/archimatetool/editor/views/tree/TreeStateHelper.java b/com.archimatetool.editor/src/com/archimatetool/editor/views/tree/TreeStateHelper.java index 4ec6ea871..851bc6859 100644 --- a/com.archimatetool.editor/src/com/archimatetool/editor/views/tree/TreeStateHelper.java +++ b/com.archimatetool.editor/src/com/archimatetool/editor/views/tree/TreeStateHelper.java @@ -7,19 +7,17 @@ import java.io.File; import java.util.ArrayList; -import java.util.Hashtable; +import java.util.HashMap; import java.util.List; +import java.util.Map; import org.eclipse.emf.ecore.EObject; import org.eclipse.jface.viewers.TreeViewer; -import org.eclipse.swt.events.DisposeEvent; -import org.eclipse.swt.events.DisposeListener; import org.eclipse.ui.IMemento; import com.archimatetool.editor.model.IEditorModelManager; import com.archimatetool.model.IArchimateModel; import com.archimatetool.model.IArchimateModelObject; -import com.archimatetool.model.IIdentifier; import com.archimatetool.model.util.ArchimateModelUtils; @@ -29,121 +27,121 @@ * * @author Phillip Beauvoir */ +@SuppressWarnings("nls") public class TreeStateHelper { public static TreeStateHelper INSTANCE = new TreeStateHelper(); - private static final String ELEMENT_SEP_CHAR = " "; //$NON-NLS-1$ + private static final String ELEMENT_SEP_CHAR = " "; - private static final String MEMENTO_EXPANDED = "expanded"; //$NON-NLS-1$ - private static final String MEMENTO_MODEL = "model"; //$NON-NLS-1$ - private static final String MEMENTO_FILE = "file"; //$NON-NLS-1$ - private static final String MEMENTO_ELEMENTS = "elements"; //$NON-NLS-1$ + private static final String MEMENTO_EXPANDED = "expanded"; + private static final String MEMENTO_MODEL = "model"; + private static final String MEMENTO_FILE = "file"; + private static final String MEMENTO_ELEMENTS = "elements"; - // Expanded tree elements or element ids for the session - private List fExpandedElements = new ArrayList(); + // Expanded tree elements that we stored on application open. + // If this is null then memento state has been initialised. + private List mementoElements = new ArrayList<>();; + + // Expanded tree elements + private List expandedElements; /** - * Flag to show we have restored from Memento first time open + * Mapping between model file and expanded element IDs */ - private boolean fRestoredFromMemento = false; + private record FileRecord(File file, String[] elementIDs) {} - private class FileMap { - File file; - String[] elements; - } + private TreeStateHelper() {} /** - * Set the Memento on Application Open - * @param memento + * Set the Memento on application start. + * This is called from {@link TreeModelView#init(org.eclipse.ui.IViewSite, IMemento)}, but we only want to do this once when the application starts. */ void setMemento(IMemento memento) { - // This is also called when the TreeView is opened, but we only want to do this once - if(memento == null || fRestoredFromMemento) { + // If expandedMementoElements is null then we have done this once on application start + if(mementoElements == null || memento == null) { return; } - // Store expanded elements as ids now, as the tree has not been created yet - for(IMemento expandedMem : memento.getChildren(MEMENTO_EXPANDED)) { + // Store expanded elements as ids now, as the tree has not been created yet. + // We will use the expanded elements later in restoreExpandedTreeElements. + IMemento expandedMem = memento.getChild(MEMENTO_EXPANDED); + if(expandedMem != null) { for(IMemento elementMem : expandedMem.getChildren(MEMENTO_MODEL)) { - String file = elementMem.getString(MEMENTO_FILE); - String elements = elementMem.getString(MEMENTO_ELEMENTS); - if(file != null && elements != null) { - FileMap fm = new FileMap(); - fm.file = new File(file); - fm.elements = elements.split(ELEMENT_SEP_CHAR); - fExpandedElements.add(fm); + String filePath = elementMem.getString(MEMENTO_FILE); + String elementIDs = elementMem.getString(MEMENTO_ELEMENTS); + if(filePath != null && elementIDs != null) { + mementoElements.add(new FileRecord(new File(filePath), elementIDs.split(ELEMENT_SEP_CHAR))); } } } - - fRestoredFromMemento = true; } /** - * Restore expanded elements on TreeView creation + * Restore expanded elements on TreeView part creation. + * This is called from {@link TreeModelView#doCreatePartControl(org.eclipse.swt.widgets.Composite) */ void restoreExpandedTreeElements(TreeViewer viewer) { - // Store expanded tree elements if View is closed - viewer.getTree().addDisposeListener(new DisposeListener() { - @Override - public void widgetDisposed(DisposeEvent e) { - fExpandedElements.clear(); - for(Object element : viewer.getVisibleExpandedElements()) { - fExpandedElements.add(element); - } + // Store expanded tree elements if TreeViewer is closed so they can be restored if the TreeViewer is re-opened + viewer.getTree().addDisposeListener(e -> { + expandedElements = new ArrayList<>(); + for(Object element : viewer.getVisibleExpandedElements()) { + expandedElements.add(element); } }); - for(Object o : fExpandedElements) { - // Actual object - if(o instanceof IArchimateModelObject) { - viewer.expandToLevel(o, 1); - } - - // String ids - if(o instanceof FileMap) { + // We are restoring for the first time from the application mememto + if(mementoElements != null) { + for(FileRecord fileRecord : mementoElements) { try { - File file = ((FileMap)o).file; - String[] elements = ((FileMap)o).elements; for(IArchimateModel model : IEditorModelManager.INSTANCE.getModels()) { - if(file.equals(model.getFile())) { - for(String id : elements) { - EObject element = ArchimateModelUtils.getObjectByID(model, id); - if(element != null) { - viewer.expandToLevel(element, 1); + // Get model from file + if(fileRecord.file().equals(model.getFile())) { + // Get object ID map + Map objectMap = ArchimateModelUtils.getObjectIDMap(model); + // Get objects from IDs + for(String id : fileRecord.elementIDs()) { + EObject object = objectMap.get(id); + if(object != null) { + viewer.expandToLevel(object, 1); } } - break; // found model + break; } } } catch(Exception ex) { - // We don't want to fail just for some stupid string operation + // We don't want to fail just for some stupid reason ex.printStackTrace(); } } + + // Done with this now + mementoElements = null; + } + // We are restoring from expanded elements + else if(expandedElements != null) { + for(Object o : expandedElements) { + viewer.expandToLevel(o, 1); + } + expandedElements = null; } - - // Allow the elements to be garbage collected - fExpandedElements.clear(); } /** - * Save expanded state of tree elements on Application close - * @param memento + * Save expanded state of tree elements on Application close. + * This is called from {@link TreeModelView#saveState(IMemento)} */ void saveStateOnApplicationClose(TreeViewer viewer, IMemento memento) { - Hashtable map = new Hashtable(); + Map map = new HashMap<>(); - IMemento expandedMem = memento.createChild(MEMENTO_EXPANDED); - - for(Object element : viewer.getVisibleExpandedElements()) { - if(element instanceof IIdentifier && element instanceof IArchimateModelObject) { - // Only store if saved in a file - File file = ((IArchimateModelObject)element).getArchimateModel().getFile(); + for(Object object : viewer.getVisibleExpandedElements()) { + if(object instanceof IArchimateModelObject modelObject) { + // Only store if model has been saved to file + File file = modelObject.getArchimateModel().getFile(); if(file != null) { - String id = ((IIdentifier)element).getId(); + // Create a string of character separated IDs + String id = modelObject.getId(); String string = map.get(file); if(string == null) { string = id; @@ -156,6 +154,12 @@ void saveStateOnApplicationClose(TreeViewer viewer, IMemento memento) { } } + if(map.isEmpty()) { + return; + } + + IMemento expandedMem = memento.createChild(MEMENTO_EXPANDED); + for(File file : map.keySet()) { IMemento elementMem = expandedMem.createChild(MEMENTO_MODEL); elementMem.putString(MEMENTO_FILE, file.getAbsolutePath());