gt: 		final Controller controller = Controller.getCurrentController();
context: /*
   *  Freeplane - mind map editor
   *  Copyright (C) 2013 Joerg Mueller, Daniel Polansky, Christian Foltin, Dimitry Polivaev
   *
   *  This file is modified by Dimitry Polivaev in 2013.
   *
   *  This program 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 2 of the License, or
   *  (at your option) any later version.
   *
   *  This program 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 this program.  If not, see <http://www.gnu.org/licenses/>.
   */
  package org.freeplane.main.application;
  
  import java.awt.Component;
  import java.awt.Container;
  import java.awt.Font;
  import java.awt.Frame;
  import java.awt.Image;
  import java.awt.Window;
  import java.awt.dnd.DropTarget;
  import java.awt.event.ActionEvent;
  import java.awt.event.ActionListener;
  import java.awt.event.WindowAdapter;
  import java.awt.event.WindowEvent;
  import java.io.ByteArrayInputStream;
  import java.io.ByteArrayOutputStream;
  import java.io.IOException;
  import java.io.ObjectInputStream;
  import java.io.ObjectOutputStream;
  import java.util.ArrayList;
  import java.util.List;
  import java.util.Vector;
  
  import javax.swing.InputMap;
  import javax.swing.JComponent;
  import javax.swing.JDesktopPane;
  import javax.swing.JFrame;
  import javax.swing.JOptionPane;
  import javax.swing.JScrollPane;
  import javax.swing.SwingUtilities;
  import javax.swing.Timer;
  import javax.swing.UIManager;
  import javax.swing.event.InternalFrameAdapter;
  import javax.swing.event.InternalFrameEvent;
  
  import org.apache.commons.codec.binary.Base64;
  import org.freeplane.core.resources.ResourceController;
  import org.freeplane.core.ui.FileOpener;
  import org.freeplane.core.ui.components.UITools;
  import org.freeplane.core.util.LogUtils;
  import org.freeplane.features.mode.Controller;
  import org.freeplane.features.ui.IMapViewChangeListener;
  import org.freeplane.features.url.mindmapmode.DroppedMindMapOpener;
  import org.freeplane.view.swing.map.MapView;
  import org.freeplane.view.swing.map.NodeView;
  import org.freeplane.view.swing.ui.DefaultMapMouseListener;
  
  import net.infonode.docking.AbstractTabWindow;
  import net.infonode.docking.DockingWindow;
  import net.infonode.docking.DockingWindowAdapter;
  import net.infonode.docking.FloatingWindow;
  import net.infonode.docking.OperationAbortedException;
  import net.infonode.docking.RootWindow;
  import net.infonode.docking.TabWindow;
  import net.infonode.docking.View;
  import net.infonode.docking.properties.DockingWindowProperties;
  import net.infonode.docking.properties.RootWindowProperties;
  import net.infonode.docking.theme.BlueHighlightDockingTheme;
  import net.infonode.docking.util.DockingUtil;
  import net.infonode.properties.gui.util.ComponentProperties;
  import net.infonode.tabbedpanel.TabAreaProperties;
  import net.infonode.tabbedpanel.TabAreaVisiblePolicy;
  import net.infonode.tabbedpanel.TabDropDownListVisiblePolicy;
  import net.infonode.tabbedpanel.TabLayoutPolicy;
  import net.infonode.tabbedpanel.TabbedPanelProperties;
  import net.infonode.tabbedpanel.titledtab.TitledTabProperties;
  import net.infonode.util.Direction;
  
  class MapViewDockingWindows implements IMapViewChangeListener {
  
  	// // 	final private Controller controller;
  	private static final String OPENED_NOW = "openedNow_1.3.04";
  	private RootWindow rootWindow = null;
  	final private Vector<Component> mapViews;
  	private boolean mPaneSelectionUpdate = true;
  	private boolean loadingLayoutFromObjectInpusStream;
  	private byte[] emptyConfigurations;
  	private final MapViewSerializer viewSerializer;
  
  	public MapViewDockingWindows() {
  		viewSerializer = new MapViewSerializer();
  		rootWindow = new RootWindow(viewSerializer);
  		configureDefaultDockingWindowProperties();
  
  		try {
  	        ByteArrayOutputStream byteStream = new ByteArrayOutputStream();
  			ObjectOutputStream wrapper = new ObjectOutputStream(byteStream);
  			rootWindow.write(wrapper);
  			wrapper.close();
  			emptyConfigurations = byteStream.toByteArray();
          }
          catch (IOException e1) {
          }
  		removeDesktopPaneAccelerators();
  		mapViews = new Vector<Component>();
  		final FileOpener fileOpener = new FileOpener("mm", new DroppedMindMapOpener());
  		new DropTarget(rootWindow, fileOpener);
  		rootWindow.addMouseListener(new DefaultMapMouseListener());
  
  		final Controller controller = Controller.getCurrentController();
  		controller.getMapViewManager().addMapViewChangeListener(this);
  		rootWindow.addListener(new DockingWindowAdapter(){
  
  			private IconColorReplacer iconColorReplacer;
  
  			@Override
              public void viewFocusChanged(View previouslyFocusedView, View focusedView) {
  				if (focusedView != null) {
  	            	Component containedMapView = getContainedMapView(focusedView);
  					final Component mapViewComponent = Controller.getCurrentController().getMapViewManager()
  					    .getMapViewComponent();
  					if (containedMapView != mapViewComponent)
  						viewSelectionChanged(containedMapView);
  	            }
              }
  
  			@Override
              public void windowClosing(DockingWindow window) throws OperationAbortedException {
  				for(Component mapViewComponent : mapViews.toArray(new Component[]{}))
  					if(SwingUtilities.isDescendingFrom(mapViewComponent, window))
  					if (!Controller.getCurrentController().getMapViewManager().close(mapViewComponent))
  						throw new OperationAbortedException("can not close view");
              }
  
  
  
  			@Override
              public void windowAdded(final DockingWindow addedToWindow, final DockingWindow addedWindow) {
  				if(addedWindow instanceof TabWindow) {
  					final DockingWindowProperties windowProperties = addedWindow.getWindowProperties();
  					windowProperties.setDockEnabled(false);
  					windowProperties.setUndockEnabled(false);
  					if(UITools.getCurrentFrame().isResizable())
  						setTabAreaVisiblePolicy((TabWindow) addedWindow);
  					else
  						setTabAreaPolicy((TabWindow) addedWindow, TabAreaVisiblePolicy.NEVER);
                  }
  				else if(addedWindow instanceof FloatingWindow) {
  					final Container topLevelAncestor = addedWindow.getTopLevelAncestor();
  					if(topLevelAncestor instanceof Window){
  						if(iconColorReplacer == null)
  							iconColorReplacer = new IconColorReplacer(((Window) UITools.getMenuComponent()).getIconImages());
  						final List<Image> iconImages = iconColorReplacer.getNextIconImages();
  						((Window)topLevelAncestor).setIconImages(iconImages);
  					}
  				}
  				setTabPolicies(addedWindow);
              }
  
  			private void setTabPolicies(final DockingWindow window) {
  				if(window instanceof TabWindow){
  					TabbedPanelProperties tabbedPanelProperties = ((TabWindow)window).getTabWindowProperties().getTabbedPanelProperties();
  					if(! tabbedPanelProperties.getTabLayoutPolicy().equals(TabLayoutPolicy.COMPRESSION))
  						tabbedPanelProperties.setTabLayoutPolicy(TabLayoutPolicy.COMPRESSION);
  					if(! tabbedPanelProperties.getTabDropDownListVisiblePolicy().equals(TabDropDownListVisiblePolicy.MORE_THAN_ONE_TAB))
  						tabbedPanelProperties.setTabDropDownListVisiblePolicy(TabDropDownListVisiblePolicy.MORE_THAN_ONE_TAB);
  				}
  				for(int i = 0; i < window.getChildWindowCount(); i++){
  					setTabPolicies(window.getChildWindow(i));
  				}
  			}
  
  
  
  			@Override
              public void windowRemoved(DockingWindow removedFromWindow, DockingWindow removedWindow) {
  				if(removedWindow instanceof TabWindow) {
  	                if (removedFromWindow == rootWindow) {
  	                	final TabAreaProperties tabAreaProperties = ((TabWindow)removedWindow).getTabWindowProperties().getTabbedPanelProperties().getTabAreaProperties();
  	                    tabAreaProperties.setTabAreaVisiblePolicy(TabAreaVisiblePolicy.ALWAYS);
                      }
                  }
              }
  		});
  
  		new InternalFrameAdapter() {
  			@Override
              public void internalFrameClosing(InternalFrameEvent e) {
              }
  		};
  
  
  	}
  
  	private void configureDefaultDockingWindowProperties() {
  
  		RootWindowProperties rootWindowProperties = rootWindow.getRootWindowProperties();
  		rootWindowProperties.addSuperObject(new BlueHighlightDockingTheme().getRootWindowProperties());
  
  		RootWindowProperties overwrittenProperties = new RootWindowProperties();
  
  		overwrittenProperties.getFloatingWindowProperties().setUseFrame(true);
  
  		final ComponentProperties windowAreaProperties = overwrittenProperties.getWindowAreaProperties();
  		windowAreaProperties.setBackgroundColor(UIManager.getColor("Panel.background"));
  		windowAreaProperties.setInsets(null);
  		windowAreaProperties.setBorder(null);
  
  		TabbedPanelProperties tabbedPanelProperties = overwrittenProperties.getTabWindowProperties().getTabbedPanelProperties();
  		tabbedPanelProperties.setTabLayoutPolicy(TabLayoutPolicy.COMPRESSION);
  		tabbedPanelProperties.setTabDropDownListVisiblePolicy(TabDropDownListVisiblePolicy.MORE_THAN_ONE_TAB);
  		tabbedPanelProperties.setShadowEnabled(false);
  
  		final ComponentProperties contentPaneComponentProperties = tabbedPanelProperties.getContentPanelProperties().getComponentProperties();
  		contentPaneComponentProperties.setInsets(null);
  		contentPaneComponentProperties.setBorder(null);
  
  		Font tabFont = new Font(Font.DIALOG, 0, 10);
  		tabFont = UITools.scaleFontInt(tabFont, 0.8);
  		TitledTabProperties titledTabProperties = overwrittenProperties.getTabWindowProperties().getTabProperties().getTitledTabProperties();
  		titledTabProperties.getHighlightedProperties().getComponentProperties().setFont(tabFont);
  		titledTabProperties.getNormalProperties().getComponentProperties().setFont(tabFont);
  		rootWindowProperties.addSuperObject(overwrittenProperties);
  	}
  
  	private void removeDesktopPaneAccelerators() {
  		 final InputMap map = new InputMap();
  		 rootWindow.setInputMap(JDesktopPane.WHEN_ANCESTOR_OF_FOCUSED_COMPONENT, map);
  	}
  
  
  	private DockingWindow getLastFocusedChildWindow(DockingWindow parentWindow) {
    	  DockingWindow lastFocusedChildWindow = parentWindow.getLastFocusedChildWindow();
    	  if(lastFocusedChildWindow == null)
    		  return parentWindow;
    	  else
    		  return getLastFocusedChildWindow(lastFocusedChildWindow);
      }
  
  	@Override
  	public void afterViewChange(final Component pOldMap, final Component pNewMap) {
  		if (pNewMap == null) {
  			return;
  		}
  		if(! loadingLayoutFromObjectInpusStream) {
  			for (int i = 0; i < mapViews.size(); ++i) {
  				if (mapViews.get(i) == pNewMap) {
  					View dockedView = getContainingDockedWindow(pNewMap);
  					Frame window = JOptionPane.getFrameForComponent(dockedView);
  					int frameState = window.getExtendedState();
  					if((frameState & Frame.ICONIFIED) != 0)
  						window.setExtendedState(frameState & ~Frame.ICONIFIED);
  					if(dockedView.isMinimized())
  						dockedView.restore();
  					else
  						dockedView.restoreFocus();
  					focusMapViewLater((MapView) pNewMap);
  					return;
  				}
  			}
  	        addDockedWindow(pOldMap, pNewMap);
          }
  		else if(mapViews.contains(pNewMap))
  			return;
  		mapViews.add(pNewMap);
  	}
  
  	static private View getContainingDockedWindow(final Component pNewMap) {
  	    return (View) SwingUtilities.getAncestorOfClass(View.class, pNewMap);
      }
  
  	private void addDockedView(View oldSelected, View newView) {
  		DockingWindow lastFocusedChildWindow = oldSelected != null ? oldSelected : getLastFocusedChildWindow(rootWindow);
  	    if(lastFocusedChildWindow == null) {
  	        DockingUtil.addWindow(newView, rootWindow);
         }
         else{
  			Container parent = SwingUtilities.getAncestorOfClass(DockingWindow.class, lastFocusedChildWindow);
  			if(parent instanceof TabWindow) {
  				final TabWindow tabWindow = (TabWindow)parent;
  				tabWindow.addTab(newView, tabWindow.getChildWindowIndex(lastFocusedChildWindow) + 1);
  			} else
  				DockingUtil.addWindow(newView, lastFocusedChildWindow.getRootWindow());
  		}
      }
  
  	static Component getContainedMapView(View dockedWindow) {
          JScrollPane scrollPane = (JScrollPane) dockedWindow.getComponent();
  		Component view = scrollPane.getViewport().getView();
          return view;
      }
  
  	private void addDockedWindow(final Component pOldMap, final Component pNewMap) {
  	    final View viewFrame = viewSerializer.newDockedView(pNewMap, createTitle(pNewMap));
  		addDockedView(pOldMap != null ? getContainingDockedWindow(pOldMap) : null, viewFrame);
      }
  
  	@Override
  	public void afterViewClose(final Component pOldMapView) {
  		for (int i = 0; i < mapViews.size(); ++i) {
  			if (mapViews.get(i) == pOldMapView) {
  				mPaneSelectionUpdate = false;
  				getContainingDockedWindow(pOldMapView).close();
  				mapViews.remove(i);
  				mPaneSelectionUpdate = true;
  				rootWindow.repaint();
  				return;
  			}
  		}
  	}
  
  	@Override
  	public void afterViewCreated(final Component mapView) {
  	}
  
  	@Override
  	public void beforeViewChange(final Component pOldMapView, final Component pNewMapView) {
  	}
  
  	private void viewSelectionChanged(final Component mapView) {
  		if (!mPaneSelectionUpdate) {
  			return;
  		}
  		Controller controller = Controller.getCurrentController();
  		if (mapView != controller.getMapViewManager().getMapViewComponent()) {
  			controller.getMapViewManager().changeToMapView(mapView.getName());
  		}
  	}
  
  	public JComponent getMapPane() {
  	    return rootWindow;
      }
  
  	public void saveLayout(){
  		ByteArrayOutputStream byteStream = new ByteArrayOutputStream();
  		try {
  	        ObjectOutputStream objectStream = new ObjectOutputStream(byteStream);
  			rootWindow.write(objectStream);
  			objectStream.close();
  			String encodedBytes = Base64.encodeBase64String(byteStream.toByteArray());
  			ResourceController.getResourceController().setProperty(OPENED_NOW, encodedBytes);
          }
          catch (IOException e) {
  	        e.printStackTrace();
          }
  	}
  
  	public void loadLayout(){
  		String encodedBytes = ResourceController.getResourceController().getProperty(OPENED_NOW, null);
  		if(encodedBytes != null){
  			byte[] bytes = Base64.decodeBase64(encodedBytes);
  			ByteArrayInputStream byteStream = new ByteArrayInputStream(bytes);
  			try {
  				loadingLayoutFromObjectInpusStream = true;
  				rootWindow.read(new ObjectInputStream(byteStream));
  			}
  			catch (Exception e) {
  				LogUtils.severe(e);
  				try {
  	                rootWindow.read(new ObjectInputStream(new ByteArrayInputStream(emptyConfigurations)));
                  }
                  catch (IOException e1) {
                  }
  			}
  			finally{
  				viewSerializer.removeDummyViews();
  				loadingLayoutFromObjectInpusStream = false;
  			}
  			rootWindow.getWindowBar(Direction.DOWN).setEnabled(false);
  		}
  	}
  
  	public void focusMapViewLater(final MapView mapView) {
  		Timer timer = new Timer(40, new ActionListener() {
  			int retryCount = 5;
  		    @Override
  			public void actionPerformed(final ActionEvent event) {
  		    	final Timer eventTimer = (Timer)event.getSource();
  		    	focusMapLater(mapView, eventTimer);
  		    }
  			private void focusMapLater(final MapView mapView, final Timer eventTimer) {
  	            if(mapView.isShowing() && Controller.getCurrentController().getMapViewManager().getMapViewComponent() == mapView){
  		    		final NodeView selected = mapView.getSelected();
  		    		if(selected != null){
  		    			final Frame frame = JOptionPane.getFrameForComponent(mapView);
  						if (frame.isFocused())
  		    				selected.requestFocusInWindow();
  						else
  							frame.addWindowFocusListener(new WindowAdapter() {
  								@Override
                                  public void windowGainedFocus(WindowEvent e) {
  									frame.removeWindowFocusListener(this);
  									selected.requestFocusInWindow();
  									retryCount = 2;
  									eventTimer.start();
                                  }
  							});
  		    		}
  		    	}
  				if(retryCount > 1){
  					retryCount--;
  					eventTimer.start();
  				}
              }
  		  });
  		timer.setRepeats(false);
  		timer.start();
      }
  
  	public void setTitle() {
  		if(loadingLayoutFromObjectInpusStream)
  			return;
  		for (Component mapViewComponent: mapViews) {
  			if (mapViewComponent instanceof MapView ) {
  	            String title = createTitle(mapViewComponent);
  	            View containingDockedWindow = getContainingDockedWindow(mapViewComponent);
  	            if(containingDockedWindow != null)
  	            	containingDockedWindow.getViewProperties().setTitle(title);
              }
  		}
      }
  
  	private String createTitle(Component mapViewComponent) {
  		MapView mapView = (MapView)mapViewComponent;
  		String name = mapView.getName();
  		String title;
  		if(mapView.getModel().isSaved() || mapView.getModel().isReadOnly())
  			title = name;
  		else
  			title = name + " *";
  		return title;
  	}
  
  	public void selectNextMapView() {
  		selectMap(1);
  	}
  
  	public void selectPreviousMapView() {
  		selectMap(-1);
  	}
  
  	private void selectMap(final int tabIndexChange) {
  