/*! ******************************************************************************
*
* Pentaho Data Integration
*
* Copyright (C) 2002-2017 by Pentaho : http://www.pentaho.com
*
*******************************************************************************
*
* Licensed 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.
*
******************************************************************************/
package org.pentaho.xul.swt.tab;
import static org.junit.Assert.*;
import static org.mockito.Mockito.*;
import org.eclipse.swt.custom.CTabFolder;
import org.eclipse.swt.custom.CTabItem;
import org.eclipse.swt.events.SelectionEvent;
import org.eclipse.swt.widgets.Composite;
import org.eclipse.swt.widgets.Event;
import org.junit.Test;
import org.mockito.invocation.InvocationOnMock;
import org.mockito.stubbing.Answer;
public class TabSetTest {
/**
* PDI-14411 NPE on Ctrl-W
*/
@Test
public void testCloseFirstTabOfTwo() {
final CTabFolder cTabFolder = mock( CTabFolder.class );
final TabSet tabSet = createTabSet( cTabFolder );
final CTabItem cTabItem1 = mock( CTabItem.class );
TabItem firstItem = createItem( tabSet, "first", "1st", cTabItem1 );
final CTabItem cTabItem2 = mock( CTabItem.class );
TabItem secondItem = createItem( tabSet, "second", "2nd", cTabItem2 );
assertEquals( 0, tabSet.indexOf( firstItem ) );
assertEquals( 1, tabSet.indexOf( secondItem ) );
tabSet.setSelected( firstItem );
assertEquals( 0, tabSet.getSelectedIndex() );
wireDisposalSelection( cTabFolder, tabSet, cTabItem1, cTabItem2 );
firstItem.dispose();
assertEquals( -1, tabSet.indexOf( firstItem ) );
assertNotNull( "selected is null", tabSet.getSelected() );
}
/**
* Ctrl-W on first and second in succession would close first and third
*/
@Test
public void testCloseFirstTabOfThree() {
final CTabFolder cTabFolder = mock( CTabFolder.class );
final TabSet tabSet = createTabSet( cTabFolder );
final CTabItem cTabItem1 = mock( CTabItem.class );
TabItem firstItem = createItem( tabSet, "first", "1st", cTabItem1 );
final CTabItem cTabItem2 = mock( CTabItem.class );
TabItem secondItem = createItem( tabSet, "second", "2nd", cTabItem2 );
TabItem thirdItem = createItem( tabSet, "third", "3rd", mock( CTabItem.class ) );
assertEquals( 0, tabSet.indexOf( firstItem ) );
assertEquals( 1, tabSet.indexOf( secondItem ) );
assertEquals( 2, tabSet.indexOf( thirdItem ) );
wireDisposalSelection( cTabFolder, tabSet, cTabItem1, cTabItem2 );
tabSet.setSelected( firstItem );
assertEquals( 0, tabSet.getSelectedIndex() );
firstItem.dispose();
assertEquals( "should select second", secondItem, tabSet.getSelected() );
}
/**
* PDI-16196 index out of bounds after closing tabs with the same name
*/
@Test
public void testDuplicateNameCloseTab() {
final CTabFolder cTabFolder = mock( CTabFolder.class );
final TabSet tabSet = createTabSet( cTabFolder );
final CTabItem cTabItem1 = mock( CTabItem.class );
TabItem firstItem = createItem( tabSet, "equalName", "equals", cTabItem1 );
final CTabItem cTabItem2 = mock( CTabItem.class );
TabItem secondItem = createItem( tabSet, "equalName", "equals", cTabItem2 );
final CTabItem cTabItem3 = mock( CTabItem.class );
TabItem thirdItem = createItem( tabSet, "different", "different", cTabItem3 );
assertEquals( 0, tabSet.indexOf( firstItem ) );
assertEquals( 1, tabSet.indexOf( secondItem ) );
wireDisposalSelection( cTabFolder, tabSet, cTabItem1, cTabItem3 );
wireDisposalSelection( cTabFolder, tabSet, cTabItem2, cTabItem3 );
firstItem.dispose();
secondItem.dispose();
tabSet.setSelected( firstItem );
assertEquals( -1, tabSet.getSelectedIndex() );
Event evt = new Event();
evt.item = cTabItem1;
evt.widget = cTabFolder;
tabSet.widgetSelected( new SelectionEvent( evt ) );
}
@Test
public void testRegularCloseTab() {
final CTabFolder cTabFolder = mock( CTabFolder.class );
final TabSet tabSet = createTabSet( cTabFolder );
final CTabItem cTabItem1 = mock( CTabItem.class );
TabItem firstItem = createItem( tabSet, "first", "1st", cTabItem1 );
final CTabItem cTabItem2 = mock( CTabItem.class );
TabItem secondItem = createItem( tabSet, "second", "2nd", cTabItem2 );
TabItem thirdItem = createItem( tabSet, "third", "3rd", mock( CTabItem.class ) );
assertEquals( 0, tabSet.indexOf( firstItem ) );
assertEquals( 1, tabSet.indexOf( secondItem ) );
assertEquals( 2, tabSet.indexOf( thirdItem ) );
// after close the previous tab is selected if available
wireDisposalSelection( cTabFolder, tabSet, cTabItem2, cTabItem1 );
tabSet.setSelected( secondItem );
assertEquals( 1, tabSet.getSelectedIndex() );
secondItem.dispose();
assertEquals( "should select first", firstItem, tabSet.getSelected() );
}
private TabSet createTabSet( final CTabFolder cTabFolder ) {
return new TabSet( null ) {
@Override
protected CTabFolder createTabFolder( Composite parent ) {
return cTabFolder;
}
};
}
private TabItem createItem( TabSet tabSet, String name, String id, final CTabItem cTabItem ) {
int[] weights = new int[] { 30, 70 };
return new TabItem( tabSet, name, id, weights ) {
@Override
protected CTabItem createTabItem( TabSet tabset ) {
return cTabItem;
}
};
}
protected void wireDisposalSelection(
final CTabFolder cTabFolder,
final TabSet tabSet,
final CTabItem closedItem,
final CTabItem nextSelectItem ) {
// emulate swt side
// on CTabItem disposal CTabFolder selects another item and notifies TabSet
final Boolean[] disposed = { false };
when( closedItem.isDisposed() ).then( new Answer<Boolean>() {
public Boolean answer( InvocationOnMock invocation ) throws Throwable {
return disposed[0];
}
} );
doAnswer( new Answer<Void>() {
public Void answer( InvocationOnMock invocation ) throws Throwable {
Event evt = new Event();
evt.item = nextSelectItem;
evt.widget = cTabFolder;
tabSet.widgetSelected( new SelectionEvent( evt ) );
disposed[0] = true;
return null;
}
} ).when( closedItem ).dispose();
}
}