private void createTab(Dockable base, Dockable dockable, int order,
			boolean select, boolean triggerEvents) {
		/*
		 * createTab() is called by : - DockView/DetachedDockView during DnD -
		 * DockTabbedPane during DnD - show() which is called by -
		 * setFloating(false) - setAutoHide(false)
		 */

		if (base == null)
			throw new NullPointerException("base must not be null");
		if (dockable == null)
			throw new NullPointerException("dockable must not be null");

		context.registerDockable(dockable); // 2007/08/11

		if (getMaximizedDockable() == base) { // 2007/08/11 added safety restore
			restore(getMaximizedDockable());
		}

		DockableState currentState = getDockableState(dockable);
		DockableState.Location currentLocation = getLocation(currentState);

		// currentState might be null CLOSED HIDDEN DOCKED FLOATING

		DockableState newState = null; // 2005/10/06 - support for floatable
										// tabs : the future state can be docked
										// or floating
		if (base.getDockKey().getLocation() == DockableState.Location.FLOATING) {
			RelativeDockablePosition position = new RelativeDockablePosition(
					dockingPanel, dockable);
			newState = new DockableState(this, dockable, base.getDockKey()
					.getLocation(), position);
		} else {
			newState = new DockableState(this, dockable, base.getDockKey()
					.getLocation());
		}

		DockableStateWillChangeEvent dswe = new DockableStateWillChangeEvent(
				currentState, newState);
		DockingActionEvent dae = new DockingActionCreateTabEvent(this,
				dockable, currentLocation, newState.getLocation(), base, order);

		// boolean stateChange = currentState == null ||
		// !currentState.isDocked();
		// boolean stateChange = currentState == null ||
		// currentState.getLocation() != newState.getLocation(); //2005/10/07
		if (triggerEvents) {
			if (!isDockingActionAccepted(dae, dswe)) {
				return; // vetoed
			}
		}

		TabbedDockableContainer dockableTab = null;
		if (currentLocation != DockableState.Location.CLOSED) {
			// don't search tabs for closed dockables // 2007/02/27
			dockableTab = DockingUtilities
					.findTabbedDockableContainer(dockable);
		}
		// TabbedDockableContainer baseTab =
		// DockingUtilities.findTabbedDockableContainer(dockable); // 2005/05/19
		TabbedDockableContainer baseTab = DockingUtilities
				.findTabbedDockableContainer(base); // 2005/05/19

		if (dockableTab != null && dockableTab != baseTab) {
			// don't belong to the same tabbed pane, so remove first the
			// dockable
			remove(dockable); // TODO : check this : removal should have been
								// done earlier (in dropRemove() )
		}

		// if ( currentState != null && (!currentState.isFloating()) &&
		// newState.isFloating()){
		if (currentState != null && currentState.isFloating()
				&& newState.isFloating()) {
			// this case is when dragging a floating dockable into another
			// floating window
			Window w = SwingUtilities
					.getWindowAncestor(dockable.getComponent());
			Window w2 = SwingUtilities.getWindowAncestor(base.getComponent());
			if (w == null) {
				// the dockable has already been removed
			} else if (w != w2) {
				// when creating a floating tab, we have to manually remove the
				// dockable
				remove(dockable);
			} else { // else same window : no need to remove it
				remove(dockable);
			}
		} else if (currentState != null && (!currentState.isFloating())
				&& newState.isFloating()) {
			// from !floating to floating :
			// when creating a floating tab, we have to manually remove the
			// dockable
			remove(dockable);
		}

		if (!newState.isFloating()) {
			// remove old attachment except when creating a floating tab
			removeFromTabbedGroup(dockable); // 2005/07/13
		}

		if (baseTab != null) {
			// add a tab
			baseTab.addDockable(dockable, order);
		} else {
			// base isn't included in a tabbed pane, so we have to create one
			DockableContainer baseOldContainer = DockingUtilities
					.findSingleDockableContainer(base);

			baseOldContainer.uninstallDocking(this);

			baseTab = DockableContainerFactory.getFactory()
					.createTabbedDockableContainer();
			baseTab.installDocking(this);
			baseTab.addDockable(base, 0);
			baseTab.addDockable(dockable, 1);

			((JTabbedPane) baseTab).addChangeListener(focusHandler); // our best
																		// way
																		// to
																		// track
																		// selection
																		// (focus)
																		// changes

			DockingUtilities.replaceChild(
					((Component) baseOldContainer).getParent(),
					(Component) baseOldContainer, (Component) baseTab);

		}
		if (select) {
			baseTab.setSelectedDockable(dockable);
		}
		// context.registerDockable(dockable); //2007/08/11
		context.setDockableState(dockable, newState);

		if (newState.isFloating() && !currentState.isFloating()) {
			// we need to store the return information
			storePreviousFloatingState(dockable, currentState);
		}

		if (triggerEvents) {
			dockable.getDockKey().setLocation(base.getDockKey().getLocation()); // 2005/10/06
			fireDockingAction(dae, new DockableStateChangeEvent(currentState,
					newState));
		}

		if (!newState.isFloating()) {
			// register tab group association except if we are going floating...
			addToTabbedGroup(base, dockable); // 2005/07/13
		}