package org.apache.maven.diagrams.gui.controller; /* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. */ import java.lang.reflect.Constructor; import java.lang.reflect.InvocationTargetException; import java.util.Iterator; import java.util.List; import org.apache.maven.diagrams.gui.bindings.layouts.LayoutBinding; import org.apache.maven.diagrams.gui.bindings.layouts.LayoutsManager; import org.apache.maven.diagrams.gui.layouts.AbstractLayoutConfiguration; import org.apache.maven.diagrams.gui.layouts.AbstractLayoutConfigurationPanel; import org.apache.maven.diagrams.gui.renderers.RendererConfiguration; import org.apache.maven.diagrams.gui.renderers.RendererNodeCache; import prefuse.Visualization; import prefuse.action.Action; import prefuse.action.ActionList; import prefuse.action.RepaintAction; import prefuse.action.layout.Layout; import prefuse.action.layout.graph.TreeLayout; import prefuse.data.Graph; import prefuse.data.Node; import prefuse.data.Tuple; import prefuse.data.tuple.TupleSet; import prefuse.visual.NodeItem; import prefuse.visual.VisualItem; import prefuse.visual.tuple.TableNodeItem; /** * @author <a href="mailto:ptab@newitech.com">Piotr Tabor</a> * @version $Id$ */ public class LayoutController { private LayoutsManager layoutsManager; private Layout currentLayout; private MainController controller; private boolean autoApplyMode; private boolean layoutRunning; public LayoutController( MainController a_controller ) { layoutsManager = new LayoutsManager(); controller = a_controller; layoutRunning = false; } @SuppressWarnings( "unchecked" ) public synchronized void updateLayoutConfiguration( AbstractLayoutConfiguration new_configuration ) { Visualization visualization = controller.getVisualization(); Layout layout = getCurrentLayout(); if ( new_configuration.canUpdateLayout( layout ) ) new_configuration.updateLayout( layout ); layout.setDuration( Layout.DEFAULT_STEP_TIME ); visualization.run( "layout" ); // visualization.putAction( "repaint", new RepaintAction() ); } // ========================= AutoApply mode ================================= public boolean isAutoApplyMode() { return autoApplyMode; } public void setAutoApplyMode( boolean autoApplyMode ) { this.autoApplyMode = autoApplyMode; } // ======================= Bindings ========================================== @SuppressWarnings( "unchecked" ) public List<LayoutBinding> getAvailableLayouts() { return layoutsManager.getLayoutBindings(); } @SuppressWarnings( "unchecked" ) public AbstractLayoutConfigurationPanel getPanelFor( String layoutName ) { Class<? extends AbstractLayoutConfigurationPanel> panelClass = layoutsManager.getEditPanelFor( layoutName ); try { AbstractLayoutConfigurationPanel<? extends AbstractLayoutConfiguration> res = panelClass.newInstance(); res.setController( this ); return res; } catch ( InstantiationException e ) { // TODO Auto-generated catch block e.printStackTrace(); return null; } catch ( IllegalAccessException e ) { // TODO Auto-generated catch block e.printStackTrace(); return null; } } @SuppressWarnings( "unchecked" ) public boolean isCurrentLayoutNamed( String layoutName ) { Layout currenLayout = getCurrentLayout(); LayoutBinding lb = layoutsManager.getBindingForName( layoutName ); if ( lb == null ) return false; return ( lb.getLayoutClass().isInstance( currenLayout ) ); } public void setCurrentLayout( String layoutName, AbstractLayoutConfiguration configuration ) { LayoutBinding lb = layoutsManager.getBindingForName( layoutName ); try { Constructor c = lb.getLayoutClass().getConstructor( new Class[] { String.class } ); currentLayout = (Layout) c.newInstance( new Object[] { "graph" } ); if ( ( configuration != null ) && ( lb.getConfigurationClass().isInstance( configuration ) ) ) configuration.updateLayout( currentLayout ); Visualization visualization = controller.getVisualization(); if ( TreeLayout.class.isInstance( currentLayout ) ) { updateRootOnTreeLayout( visualization, (TreeLayout) currentLayout ); } visualization.cancel( "layout" ); ActionList layoutList = new ActionList( layoutRunning ? Action.INFINITY : Action.DEFAULT_STEP_TIME ); layoutList.add( currentLayout ); layoutList.add( new RepaintAction() ); visualization.putAction( "layout", layoutList ); visualization.run( "layout" ); visualization.putAction( "refresh", new RepaintAction() ); } catch ( InstantiationException e ) { // TODO Auto-generated catch block e.printStackTrace(); } catch ( IllegalAccessException e ) { // TODO Auto-generated catch block e.printStackTrace(); } catch ( SecurityException e ) { // TODO Auto-generated catch block e.printStackTrace(); } catch ( NoSuchMethodException e ) { // TODO Auto-generated catch block e.printStackTrace(); } catch ( IllegalArgumentException e ) { // TODO Auto-generated catch block e.printStackTrace(); } catch ( InvocationTargetException e ) { // TODO Auto-generated catch block e.printStackTrace(); } } public void updateRootOnTreeLayout( Visualization visualization, TreeLayout currentLayout2 ) { Tuple root = null; int min_in = Integer.MAX_VALUE; Graph graph = (Graph) visualization.getGroup( "graph" ); Iterator<Tuple> iterator = graph.tuples(); while ( iterator.hasNext() ) { Tuple t = iterator.next(); if ( TableNodeItem.class.isInstance( t ) ) { // System.out.print( t.get( "node" ).toString().substring( 0, 50 ) + ":" ); TableNodeItem t2 = (TableNodeItem) t; int t2_out_count = count( t2.outEdges() ); if ( t2_out_count < min_in ) { root = t; min_in = t2_out_count; } // System.out.print( t2.getChildCount() + ": in=" + count( t2.inEdges() ) + " out=" // + + " all=" + count( t2.edges() ) + ";" ); // System.out.println( " degree=" + t2.getDegree() ); } } if ( root != null ) { VisualItem vi = visualization.getVisualItem( "graph", root ); ( (TreeLayout) currentLayout ).setLayoutRoot( (NodeItem) vi ); } } private int count( Iterator inEdges ) { int i = 0; while ( inEdges.hasNext() ) { inEdges.next(); i++; } return i; } public Layout getCurrentLayout() { if ( currentLayout == null ) { Visualization visualization = controller.getVisualization(); if ( visualization != null ) currentLayout = searchForLayout( visualization.getAction( "layout" ) ); else return null; } return currentLayout; } private Layout searchForLayout( Action action ) { if ( Layout.class.isInstance( action ) ) return (Layout) action; if ( ActionList.class.isInstance( action ) ) { ActionList al = (ActionList) action; for ( int i = 0; i < al.size(); i++ ) { Layout res = searchForLayout( al.get( i ) ); if ( res != null ) return res; } } return null; } @SuppressWarnings( "unchecked" ) public AbstractLayoutConfiguration provideConfigurationForLayoutNamed( String layoutName ) throws InstantiationException, IllegalAccessException { Layout currenLayout = getCurrentLayout(); LayoutBinding lb = layoutsManager.getBindingForName( layoutName ); AbstractLayoutConfiguration<Layout> conf = (AbstractLayoutConfiguration<Layout>) lb.getConfigurationClass().newInstance(); if ( lb.getLayoutClass().isInstance( currenLayout ) ) { conf.readFromLayout( currenLayout ); } else { conf.setDefaultConfiguration(); } return conf; } public void startLayoutRunning() { Visualization visualization = controller.getVisualization(); Action layout = visualization.getAction( "layout" ); layout.setDuration( Action.INFINITY ); if ( !layout.isRunning() ) layout.run(); layoutRunning = true; } public void stopLayoutRunning() { Visualization visualization = controller.getVisualization(); Action layout = visualization.getAction( "layout" ); layout.setDuration( 0 ); layoutRunning = false; } public void updateRendererConfiguration( RendererConfiguration currentRendererConfiguration ) { controller.getRenderer().setConfiguration( currentRendererConfiguration ); clearRenderersCache(); controller.getVisualization().run( "refresh" ); } private void clearRenderersCache() { for ( Iterator<VisualItem> i = controller.getVisualization().items(); i.hasNext(); ) { VisualItem item = i.next(); item.set( RendererNodeCache.CACHE_ITEM_COLUMN_NAME, null ); } } }