package org.freeplane.plugin.workspace.mindmapmode;
import java.io.File;
import java.net.URI;
import java.util.Enumeration;
import java.util.List;
import org.freeplane.core.resources.ResourceController;
import org.freeplane.core.resources.components.ComboProperty;
import org.freeplane.core.resources.components.IPropertyControl;
import org.freeplane.core.resources.components.IPropertyControlCreator;
import org.freeplane.core.resources.components.OptionPanelBuilder;
import org.freeplane.core.ui.IndexedTree;
import org.freeplane.core.util.LogUtils;
import org.freeplane.features.link.mindmapmode.MLinkController;
import org.freeplane.features.map.NodeModel;
import org.freeplane.features.mode.ModeController;
import org.freeplane.plugin.workspace.URIUtils;
import org.freeplane.plugin.workspace.WorkspaceController;
import org.freeplane.plugin.workspace.features.WorkspaceMapModelExtension;
import org.freeplane.plugin.workspace.model.project.AWorkspaceProject;
public class MModeWorkspaceLinkController extends MLinkController {
public final static int LINK_RELATIVE_TO_PROJECT = 2;
private final static String LINK_RELATIVE_TO_PROJECT_PROPERTY = "relative_to_workspace";
private static MModeWorkspaceLinkController self;
protected void init(ModeController modeController) {
setModeController(modeController);
}
public static MModeWorkspaceLinkController getController() {
// final ModeController modeController = Controller.getCurrentModeController();
// return (MModeWorkspaceLinkController) getController(modeController);
if(self == null) {
self = new MModeWorkspaceLinkController();
}
return self;
}
public void setLink(final NodeModel node, final URI argUri, final int linkType) {
URI uri = argUri;
int finalLinkType = linkType;
if (linkType == LINK_RELATIVE_TO_PROJECT) {
WorkspaceMapModelExtension mapExt = WorkspaceController.getMapModelExtension(node.getMap());
if(mapExt != null && mapExt.getProject() != null) {
uri = mapExt.getProject().getRelativeURI(argUri);
if(uri == null) {
uri = argUri;
}
else {
finalLinkType = LINK_ABSOLUTE;
}
}
else {
if(node.getMap().getFile() != null) {
finalLinkType = LINK_RELATIVE_TO_MINDMAP;
}
else {
finalLinkType = LINK_ABSOLUTE;
}
}
}
super.setLink(node, uri, finalLinkType);
}
public int linkType() {
String linkTypeProperty = ResourceController.getResourceController().getProperty("links");
if (linkTypeProperty.equals(LINK_RELATIVE_TO_PROJECT_PROPERTY)) {
return LINK_RELATIVE_TO_PROJECT;
}
return super.linkType();
}
public URI createRelativeURI(final File base, final File input, final int linkType) {
if (linkType == LINK_ABSOLUTE) {
return null;
}
try {
if (linkType == LINK_RELATIVE_TO_PROJECT) {
AWorkspaceProject project = WorkspaceController.getMapProject();
if (project != null) {
return project.getRelativeURI(input.getAbsoluteFile().toURI());
}
}
if (base == null) {
return input.toURI().normalize();
}
else {
return super.createRelativeURI(base, input, linkType);
}
}
catch (Exception e) {
LogUtils.warn(e);
}
return null;
}
/**
* similar to the File(File base, File ext) contructor. The extend path (child) will be appended to the base path.
* @param base
* @param child
* @return
*/
public static URI extendPath(URI base, String child) {
return new File(URIUtils.getAbsoluteFile(base), child).toURI();
}
public void prepareOptionPanelBuilder(OptionPanelBuilder builder) {
IndexedTree.Node node = (IndexedTree.Node) builder.getRoot();
String path = "Environment/hyperlink_types/links";
final IndexedTree.Node found = getNodeForPath(path, node);
if(found != null) {
found.setUserObject(new IPropertyControlCreator() {
private final IPropertyControlCreator creator = (IPropertyControlCreator) found.getUserObject();
public IPropertyControl createControl() {
ComboProperty property = (ComboProperty) creator.createControl();
List<String> list = property.getPossibleValues();
list.add(MModeWorkspaceLinkController.LINK_RELATIVE_TO_PROJECT_PROPERTY);
return new ComboProperty("links", list.toArray(new String[] {}));
}
});
}
}
private IndexedTree.Node getNodeForPath(String path, IndexedTree.Node node) {
Enumeration<?> children = node.children();
while(children.hasMoreElements()) {
IndexedTree.Node child = (IndexedTree.Node)children.nextElement();
if(child.getKey() != null && path.startsWith(child.getKey().toString())) {
if(path.equals(child.getKey().toString())) {
return child;
}
return getNodeForPath(path, child);
}
}
return null;
}
}