/******************************************************************************* * Copyright © 2008, 2013 IBM Corporation and others. * All rights reserved. This program and the accompanying materials * are made available under the terms of the Eclipse Public License v1.0 * which accompanies this distribution, and is available at * http://www.eclipse.org/legal/epl-v10.html * * Contributors: * IBM Corporation - initial API and implementation * *******************************************************************************/ package org.eclipse.edt.ide.rui.visualeditor.internal.widget; import java.util.ArrayList; import java.util.Collection; import java.util.Iterator; import java.util.List; import java.util.TreeSet; import org.eclipse.edt.ide.rui.visualeditor.internal.jsonvisitors.JsonVisitor; import org.eclipse.edt.ide.rui.visualeditor.internal.util.ComparatorWidgetPositions; import org.eclipse.edt.ide.rui.visualeditor.internal.widget.layout.WidgetLayoutRegistry; import org.eclipse.edt.javart.json.JsonParser; import org.eclipse.edt.javart.json.ObjectNode; import org.eclipse.edt.javart.json.ParseException; import org.eclipse.swt.graphics.Point; /** * Manages a list of widget parts */ public class WidgetManager { protected WidgetPart _widgetRoot = null; protected TreeSet _widgetPartsTree = null; protected List _listWidgetParts = null; /** * Constructor. A root widget is created that represents the RUI Handler. */ public WidgetManager() { _widgetRoot = new WidgetPart(); _widgetRoot.setTypeName( WidgetLayoutRegistry.ROOT ); _widgetPartsTree = new TreeSet( new ComparatorWidgetPositions() ); _listWidgetParts = new ArrayList(); } /** * Recursively adds widgets to the tree set. */ protected void addChildrenToSortedSet( TreeSet treeset, WidgetPart widgetPart ) { List listChildren = widgetPart.getChildren(); for( int i = 0; i < listChildren.size(); ++i ) { WidgetPart widgetChild = (WidgetPart)listChildren.get( i ); treeset.add( widgetChild ); addChildrenToSortedSet( treeset, widgetChild ); } } /** * */ public void addWidget( WidgetPart widgetParent, WidgetPart widgetChild ) { widgetParent.addChildWidget( widgetChild ); } /** * Finds the widget with the given statement offset and length. */ public WidgetPart getWidget( int iOffset, int iLength ) { Collection widgets = getWidgetList(); for( Iterator iterWidgets = widgets.iterator(); iterWidgets.hasNext(); ) { WidgetPart widget = (WidgetPart)iterWidgets.next(); if( widget.getStatementOffset() == iOffset && widget.getStatementLength() == iLength ) return widget; } return null; } /** * Returns the number of widgets. */ public int getWidgetCount() { return getWidgetList().size(); } /** * Returns the next widget in the list of widgets sorted by statement location. */ public WidgetPart getWidgetNext( WidgetPart widget ) { WidgetPart widgetNext = null; List listChildren = widget.getChildren(); // Next sibling //------------- if( listChildren.size() > 0 ) widgetNext = (WidgetPart)listChildren.get( 0 ); // Locate the next sibling of an ascendant //---------------------------------------- else { WidgetPart widgetParent = widget; // Go through the parent hierarchy //-------------------------------- while( true ) { widget = widgetParent; widgetParent = widgetParent.getParent(); // Parent is the root //------------------- if( widgetParent == null ){ widgetNext = (WidgetPart)_widgetRoot.getChildren().get( 0 ); break; } int iIndex = widgetParent.getChildIndex( widget ); listChildren = widgetParent.getChildren(); if( iIndex < listChildren.size() - 1 ){ widgetNext = (WidgetPart)listChildren.get( iIndex + 1 ); break; } } } return widgetNext; } /** * Returns the previous widget in the hierarchy tree. */ public WidgetPart getWidgetPrevious( WidgetPart widget ) { WidgetPart widgetPrevious = null; WidgetPart widgetParent = widget.getParent(); int iIndex = widgetParent.getChildIndex( widget ); if( iIndex == 0 ) { if( widgetParent != _widgetRoot ) return widgetParent; widgetPrevious = (WidgetPart)widgetParent.getChildren().get( widgetParent.getChildren().size() - 1 ); } else widgetPrevious = (WidgetPart)widgetParent.getChildren().get( iIndex - 1 ); // Find the lowest leaf //--------------------- while( true ) { List listChildren = widgetPrevious.getChildren(); if( listChildren.size() == 0 ) break; widgetPrevious = (WidgetPart)listChildren.get( listChildren.size() - 1 ); } return widgetPrevious; } /** * Returns the root widget, which represents the RUI Handler. */ public WidgetPart getWidgetRoot() { return _widgetRoot; } /** * Returns an unordered set of widget parts. */ public List getWidgetList(){ return _listWidgetParts; } /** * Recursively adds widgets to the unordered list. */ public void getWidgetListRecursive( List listWidgetParts, WidgetPart widgetPart ) { List listChildren = widgetPart.getChildren(); for( int i = 0; i < listChildren.size(); ++i ) { WidgetPart widgetChild = (WidgetPart)listChildren.get( i ); listWidgetParts.add( widgetChild ); getWidgetListRecursive( listWidgetParts, widgetChild ); } } /* * Return true is WidgetPart child is really the child of WidgetPart parent, or false. */ public boolean isChildOf( WidgetPart child, WidgetPart parent ) { if ( parent == _widgetRoot && child != _widgetRoot ) { return true; } if ( child.getParent() == _widgetRoot ) { return false; } if ( child.getParent() == parent ) { return true; } return isChildOf( child.getParent(), parent ); } /** * Returns a collection of widgets sorted by position order, with smaller origins first. */ public List getWidgets( Point point ) { // Filter the list to those under the point //----------------------------------------- ArrayList list = new ArrayList(); Iterator iterWidgets = _widgetPartsTree.iterator(); while( iterWidgets.hasNext() == true ) { WidgetPart widget = (WidgetPart)iterWidgets.next(); if( widget.getBounds().contains( point ) == true ) list.add( widget ); } return list; } /** * Returns whether there are any widgets. */ public boolean hasWidgets() { return _widgetRoot.getChildren().isEmpty() == false; } /** * Removes all widgets. */ public void removeAllWidgets() { _widgetRoot.removeAllChildren(); _widgetPartsTree.clear(); _listWidgetParts.clear(); } /** * Traverses the widget tree removing invalid widgets from the leaves to the root. */ protected void removeInvalidWidgets() { removeInvalidWidgetsRecursive( _widgetRoot ); } /** * Recursively removes widgets that have invalid characteristics. */ protected void removeInvalidWidgetsRecursive( WidgetPart widget ) { // Do the children first. // Traverse backward through the children so they // can be removed while going through the list //----------------------------------------------- List listChildren = widget.getChildren(); for( int i = listChildren.size() - 1; i >= 0; i-- ) removeInvalidWidgetsRecursive( (WidgetPart)listChildren.get( i ) ); // If the children are parented by this widget in an external RUI handler, // this widget will have an invalid statement. Remove its children. //------------------------------------------------------------------------ if( widget != _widgetRoot ) if( widget._iStatementOffset < 0 || widget._iStatementLength <= 0 ) widget.removeAllChildren(); // Check the widget for invalid characteristics //--------------------------------------------- if( widget._rectBounds.isEmpty() || widget.getTypeName() == null ) removeWidget( widget ); else if( ( widget._iStatementOffset < 0 || widget._iStatementLength <= 0 ) && widget.getMoveable() == false ) removeWidget( widget ); } /** * Removes a widget from its parent's list of child widgets. */ public void removeWidget( WidgetPart widgetPart ) { WidgetPart widgetParent = widgetPart.getParent(); if( widgetParent == null ) return; List listChildren = widgetParent.getChildren(); listChildren.remove( widgetPart ); } /** * A Json string has been received from the browser in response to a get widget information request. * This method removes all existing widget parts and creates new ones by parsing the Json string. */ public void setWidgetsFromJsonString( String strJson ) { removeAllWidgets(); // The Json parser uses the widget part given to it // as the top level part, so we need to create it ahead of time // and check it after the parse to see if it was used. //------------------------------------------------------------- try { ObjectNode node = JsonParser.parse( strJson ); try { node.accept( new JsonVisitor( _widgetRoot ) ); } catch( RuntimeException ex ) { } } catch( ParseException ex ) { } // Obtain a list of all widgets sorted by position //------------------------------------------------ addChildrenToSortedSet( _widgetPartsTree, _widgetRoot ); getWidgetListRecursive( _listWidgetParts, _widgetRoot ); // Debug only //----------- if( false ) _widgetRoot.printWidgetTree( 0 ); // Remove any invalid widgets //--------------------------- // Yun Feng: the invalid widgets have been filtered out in browser. //removeInvalidWidgets(); } }