Skip to content

Commit

Permalink
Refactor TreeStateHelper
Browse files Browse the repository at this point in the history
- Improved readability and optimised
  • Loading branch information
Phillipus committed Jan 20, 2025
1 parent 2a6d09d commit 97bdef9
Showing 1 changed file with 75 additions and 71 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -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;


Expand All @@ -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<Object> fExpandedElements = new ArrayList<Object>();
// Expanded tree elements that we stored on application open.
// If this is null then memento state has been initialised.
private List<FileRecord> mementoElements = new ArrayList<>();;

// Expanded tree elements
private List<Object> 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<String, EObject> 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<File, String> map = new Hashtable<File, String>();
Map<File, String> 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;
Expand All @@ -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());
Expand Down

0 comments on commit 97bdef9

Please sign in to comment.