org.freeplane.main.application.MapViewDockingWindows.java Source code

Java tutorial

Introduction

Here is the source code for org.freeplane.main.application.MapViewDockingWindows.java

Source

/*
 *  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.Frame;
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.Vector;

import javax.swing.InputMap;
import javax.swing.JComponent;
import javax.swing.JDesktopPane;
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 net.infonode.docking.DockingWindow;
import net.infonode.docking.DockingWindowAdapter;
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.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.util.Direction;

import org.apache.commons.codec.binary.Base64;
import org.freeplane.core.resources.ResourceController;
import org.freeplane.core.util.LogUtils;
import org.freeplane.features.mode.Controller;
import org.freeplane.features.ui.IMapViewChangeListener;
import org.freeplane.features.url.mindmapmode.FileOpener;
import org.freeplane.view.swing.map.MapView;
import org.freeplane.view.swing.map.NodeView;
import org.freeplane.view.swing.ui.DefaultMapMouseListener;

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);
        RootWindowProperties rootWindowProperties = rootWindow.getRootWindowProperties();
        rootWindowProperties.addSuperObject(new BlueHighlightDockingTheme().getRootWindowProperties());
        rootWindowProperties.getWindowAreaProperties().setBackgroundColor(UIManager.getColor("Panel.background"));
        rootWindow.getWindowBar(Direction.DOWN).setEnabled(true);
        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();
        new DropTarget(rootWindow, fileOpener);
        rootWindow.addMouseListener(new DefaultMapMouseListener());

        final Controller controller = Controller.getCurrentController();
        controller.getMapViewManager().addMapViewChangeListener(this);
        rootWindow.addListener(new DockingWindowAdapter() {

            @Override
            public void viewFocusChanged(View previouslyFocusedView, View focusedView) {
                if (previouslyFocusedView != null && focusedView != null) {
                    Component containedMapView = getContainedMapView(focusedView);
                    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, false))
                            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);
                    final TabAreaProperties tabAreaProperties = ((TabWindow) addedWindow).getTabWindowProperties()
                            .getTabbedPanelProperties().getTabAreaProperties();
                    if (addedToWindow == rootWindow)
                        tabAreaProperties.setTabAreaVisiblePolicy(TabAreaVisiblePolicy.MORE_THAN_ONE_TAB);
                    else
                        tabAreaProperties.setTabAreaVisiblePolicy(TabAreaVisiblePolicy.ALWAYS);
                }
                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 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);
    }

    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);
                    if (dockedView.isMinimized())
                        dockedView.restore();
                    else
                        dockedView.restoreFocus();
                    focusMapViewLater((MapView) pNewMap);
                    return;
                }
            }
            addDockedWindow(pNewMap);
        } else if (mapViews.contains(pNewMap))
            return;
        mapViews.add(pNewMap);
    }

    static private View getContainingDockedWindow(final Component pNewMap) {
        return (View) SwingUtilities.getAncestorOfClass(View.class, pNewMap);
    }

    protected void addDockedView(View dynamicView) {
        DockingWindow lastFocusedChildWindow = getLastFocusedChildWindow(rootWindow);
        if (lastFocusedChildWindow == null) {
            DockingUtil.addWindow(dynamicView, rootWindow);
        } else {
            Container parent = SwingUtilities.getAncestorOfClass(DockingWindow.class, lastFocusedChildWindow);
            if (parent instanceof TabWindow)
                ((TabWindow) parent).addTab(dynamicView);
            else
                DockingUtil.addWindow(dynamicView, lastFocusedChildWindow.getRootWindow());
        }
    }

    static Component getContainedMapView(View dockedWindow) {
        JScrollPane scrollPane = (JScrollPane) dockedWindow.getComponent();
        Component view = scrollPane.getViewport().getView();
        return view;
    }

    private void addDockedWindow(final Component pNewMap) {
        final View viewFrame = viewSerializer.newDockedView(pNewMap);
        addDockedView(viewFrame);
    }

    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;
            }
        }
    }

    public void afterViewCreated(final Component mapView) {
    }

    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;
            }
        }
    }

    public void focusMapViewLater(final MapView mapView) {
        Timer timer = new Timer(40, new ActionListener() {
            int retryCount = 5;

            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) {
                MapView mapView = (MapView) mapViewComponent;
                String name = mapView.getName();
                String title;
                if (mapView.getModel().isSaved())
                    title = name;
                else
                    title = name + " *";
                View containingDockedWindow = getContainingDockedWindow(mapViewComponent);
                containingDockedWindow.getViewProperties().setTitle(title);
            }
        }
    }
}