/******************************************************************************* * Copyright (c) 2013, 2015 EclipseSource 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: * EclipseSource - initial API and implementation ******************************************************************************/ package org.eclipse.swt.internal.widgets.coolitemkit; import static org.eclipse.rap.rwt.internal.lifecycle.WidgetUtil.getAdapter; import org.eclipse.rap.json.JsonObject; import org.eclipse.rap.rwt.internal.lifecycle.ProcessActionRunner; import org.eclipse.rap.rwt.internal.protocol.WidgetOperationHandler; import org.eclipse.swt.graphics.Rectangle; import org.eclipse.swt.internal.widgets.ICoolBarAdapter; import org.eclipse.swt.internal.widgets.Props; import org.eclipse.swt.widgets.CoolBar; import org.eclipse.swt.widgets.CoolItem; public class CoolItemOperationHandler extends WidgetOperationHandler<CoolItem> { private static final String METHOD_MOVE = "move"; private static final String PROP_LEFT = "left"; public CoolItemOperationHandler( CoolItem item ) { super( item ); } @Override public void handleCall( CoolItem item, String method, JsonObject properties ) { if( METHOD_MOVE.equals( method ) ) { handleCallMove( item, properties ); } } /* * PROTOCOL CALL move * * @param left (int) the left position of the cool item */ public void handleCallMove( final CoolItem item, JsonObject properties ) { final int newLeft = properties.get( PROP_LEFT ).asInt(); ProcessActionRunner.add( new Runnable() { @Override public void run() { moveItem( item, newLeft ); } } ); } static void moveItem( CoolItem coolItem, int newX ) { CoolItem[] items = coolItem.getParent().getItems(); boolean changed = false; int newOrder = -1; int maxX = 0; int minX = 0; for( int i = 0; newOrder == -1 && i < items.length; i++ ) { CoolItem item = items[ i ]; Rectangle itemBounds = item.getBounds(); if( item != coolItem && itemBounds.contains( newX, itemBounds.y ) ) { if( coolItem.getBounds().x > newX ) { newOrder = i + 1; } else { newOrder = i; } changed = changeOrder( coolItem, newOrder ); } maxX = Math.max( maxX, itemBounds.x + itemBounds.width ); minX = Math.min( minX, itemBounds.x ); } if( newOrder == -1 && newX > maxX ) { // item was moved after the last item int last = coolItem.getParent().getItemCount() - 1; changed = changeOrder( coolItem, last ); } else if( newOrder == -1 && newX < minX ) { // item was moved before the first item changed = changeOrder( coolItem, 0 ); } // In case an item was moved but that didn't cause it to change its order, // we need to let it 'snap back' to its previous position if( !changed ) { // TODO [rh] HACK: a decent solution would mark the item as 'bounds // changed' and that mark could be evaluated by writeBounds. // A more flexible writeBounds implementation on WidgetLCAUtil is // necessary therefore. getAdapter( coolItem ).preserve( Props.BOUNDS, null ); } } private static boolean changeOrder( CoolItem coolItem, int newOrder ) { boolean result; CoolBar coolBar = coolItem.getParent(); int itemIndex = coolBar.indexOf( coolItem ); int[] itemOrder = coolBar.getItemOrder(); int length = itemOrder.length; int[] targetOrder = new int[ length ]; int index = 0; if ( itemIndex != newOrder ) { for( int i = 0; i < length; i++ ) { if( i == newOrder ) { targetOrder[ i ] = itemOrder[ itemIndex ]; } else { if( index == itemIndex ) { index++; } targetOrder[ i ] = itemOrder[ index ]; index++; } } coolBar.getAdapter( ICoolBarAdapter.class ).setItemOrder( targetOrder ); result = true; } else { result = false; } return result; } }