/*! ******************************************************************************
*
* 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 java.util.ArrayList;
import java.util.List;
import org.eclipse.swt.SWT;
import org.eclipse.swt.custom.CTabFolder;
import org.eclipse.swt.custom.CTabFolder2Listener;
import org.eclipse.swt.custom.CTabFolderEvent;
import org.eclipse.swt.events.KeyAdapter;
import org.eclipse.swt.events.SelectionEvent;
import org.eclipse.swt.events.SelectionListener;
import org.eclipse.swt.graphics.Font;
import org.eclipse.swt.widgets.Composite;
import org.eclipse.swt.widgets.Event;
import org.eclipse.swt.widgets.Listener;
public class TabSet implements SelectionListener, CTabFolder2Listener {
protected CTabFolder tabfolder;
protected List<TabItem> tabList = new ArrayList<TabItem>();
protected int selectedIndex = -1;
protected Font changedFont;
protected Font unchangedFont;
private List<TabListener> listeners = new ArrayList<TabListener>();
public List<TabItem> lastUsedTabs = new ArrayList<TabItem>();
public TabSet( Composite parent ) {
super();
tabfolder = createTabFolder( parent );
tabfolder.setSimple( false );
tabfolder.setUnselectedImageVisible( true );
tabfolder.setUnselectedCloseVisible( true );
tabfolder.addSelectionListener( this );
tabfolder.addCTabFolder2Listener( this );
workaroundTabChevronOverflow( tabfolder );
}
private void workaroundTabChevronOverflow( CTabFolder tabfolder ) {
// hack to prevent two tab rows on swt 4.6+
// eclipse bug #499215
tabfolder.addListener( SWT.Resize, new Listener() {
@Override
public void handleEvent( Event event ) {
int idx = tabfolder.getSelectionIndex();
if ( idx > 0 && isTabOverflowing( tabfolder ) ) {
// trigger CTabFolder.updateTabHeight
tabfolder.setSelection( idx - 1 );
tabfolder.setSelection( idx );
}
}
private boolean isTabOverflowing( CTabFolder tabfolder ) {
// overflow happens when size of inner toolbar exceeds assigned tabHeight
return ( tabfolder.getChildren().length > 0
&& tabfolder.getChildren()[0].getSize().y > tabfolder.getTabHeight() );
}
} );
}
public void widgetSelected( SelectionEvent event ) {
if ( selectedIndex >= 0 && selectedIndex < tabList.size() ) {
TabItem deSelectedTabItem = tabList.get( selectedIndex );
if ( deSelectedTabItem != null ) {
notifyDeselectListeners( deSelectedTabItem );
}
}
for ( int i = 0; i < tabList.size(); i++ ) {
TabItem item = tabList.get( i );
if ( event.item.equals( item.getSwtTabItem() ) ) {
selectedIndex = i;
notifySelectListeners( item );
}
}
}
public void widgetDefaultSelected( SelectionEvent event ) {
widgetSelected( event );
}
public void close( CTabFolderEvent event ) {
for ( int i = 0; i < tabList.size(); i++ ) {
TabItem item = tabList.get( i );
if ( event.item.equals( item.getSwtTabItem() ) ) {
event.doit = notifyCloseListeners( item );
}
}
}
public void maximize( CTabFolderEvent event ) {
}
public void minimize( CTabFolderEvent event ) {
}
public void showList( CTabFolderEvent event ) {
}
public void restore( CTabFolderEvent event ) {
}
public void notifySelectListeners( TabItem item ) {
for ( int i = 0; i < listeners.size(); i++ ) {
( listeners.get( i ) ).tabSelected( item );
}
// add to the lat used tab
addItemToHistory( item );
}
protected CTabFolder createTabFolder( Composite parent ) {
return new CTabFolder( parent, SWT.MULTI );
}
/**
* Add a tab item to the tab usage history
*
* @param item
* the tab item to add
*/
private void addItemToHistory( TabItem item ) {
// Just don't add the same item twice in a row
//
if ( lastUsedTabs.size() == 0 || lastUsedTabs.lastIndexOf( item ) != lastUsedTabs.size() - 1 ) {
lastUsedTabs.add( item );
}
}
/**
* Remove all occurrences of the specified item from the last used list.
*
* @param item
* the tab item to remove
*/
private void removeItemFromHistory( TabItem item ) {
// Remove
boolean removed;
do {
removed = lastUsedTabs.remove( item );
} while ( removed );
}
public void notifyDeselectListeners( TabItem item ) {
for ( int i = 0; i < listeners.size(); i++ ) {
( listeners.get( i ) ).tabDeselected( item );
}
}
public boolean notifyCloseListeners( TabItem item ) {
boolean doit = item.notifyCloseListeners();
for ( int i = 0; i < listeners.size(); i++ ) {
doit &= ( listeners.get( i ) ).tabClose( item );
}
if ( doit ) {
removeItemFromHistory( item );
selectLastUsedTab();
}
return doit;
}
/**
* Select the last tab in the tab usage history list
*/
private void selectLastUsedTab() {
int historySize = lastUsedTabs.size();
if ( historySize > 0 ) {
TabItem lastItem = lastUsedTabs.get( historySize - 1 );
setSelected( lastItem );
}
}
public CTabFolder getSwtTabset() {
return tabfolder;
}
public void addTab( TabItem item ) {
tabList.add( item );
}
public void addKeyListener( KeyAdapter keys ) {
tabfolder.addKeyListener( keys );
}
public int getSelectedIndex() {
return selectedIndex;
}
public TabItem getSelected() {
if ( selectedIndex >= 0 && selectedIndex < tabList.size() ) {
return tabList.get( selectedIndex );
}
return null;
}
public int indexOf( TabItem item ) {
return tabList.indexOf( item );
}
public void setSelected( int index ) {
if ( index >= 0 && index < tabList.size() ) {
TabItem item = ( tabList.get( index ) );
tabfolder.setSelection( item.getSwtTabItem() );
selectedIndex = index;
notifySelectListeners( tabList.get( index ) );
}
}
public void setSelected( TabItem item ) {
selectedIndex = indexOf( item );
if ( selectedIndex != -1 ) {
setSelected( selectedIndex );
}
}
public void remove( TabItem item ) {
int itemIndex = tabList.indexOf( item );
if ( itemIndex >= 0 && itemIndex < selectedIndex ) {
// removal would change selected
selectedIndex--;
}
tabList.remove( item );
item.dispose();
}
public Font getChangedFont() {
return changedFont;
}
public void setChangedFont( Font changedFont ) {
this.changedFont = changedFont;
}
public Font getUnchangedFont() {
return tabfolder.getDisplay().getSystemFont();
}
public void addListener( TabListener listener ) {
listeners.add( listener );
}
public void removeListener( TabListener listener ) {
listeners.remove( listener );
}
}