/*******************************************************************************
 * Copyright (c) 2000, 2016 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.swt.widgets;


import org.eclipse.swt.*;
import org.eclipse.swt.graphics.*;
import org.eclipse.swt.internal.*;
import org.eclipse.swt.internal.gtk.*;

/**
 * Instances of this class provide an etched border
 * with an optional title.
 * <p>
 * Shadow styles are hints and may not be honoured
 * by the platform.  To create a group with the
 * default shadow style for the platform, do not
 * specify a shadow style.
 * <dl>
 * <dt><b>Styles:</b></dt>
 * <dd>SHADOW_ETCHED_IN, SHADOW_ETCHED_OUT, SHADOW_IN, SHADOW_OUT, SHADOW_NONE</dd>
 * <dt><b>Events:</b></dt>
 * <dd>(none)</dd>
 * </dl>
 * <p>
 * Note: Only one of the above styles may be specified.
 * </p><p>
 * IMPORTANT: This class is <em>not</em> intended to be subclassed.
 * </p>
 *
 * @see <a href="http://www.eclipse.org/swt/examples.php">SWT Example: ControlExample</a>
 * @see <a href="http://www.eclipse.org/swt/">Sample code and further information</a>
 * @noextend This class is not intended to be subclassed by clients.
 */
public class Group extends Composite {
	long /*int*/ clientHandle, labelHandle;
	String text = "";
	// We use this to keep track of the foreground color
	GdkRGBA foreground;

/**
 * Constructs a new instance of this class given its parent
 * and a style value describing its behavior and appearance.
 * <p>
 * The style value is either one of the style constants defined in
 * class <code>SWT</code> which is applicable to instances of this
 * class, or must be built by <em>bitwise OR</em>'ing together
 * (that is, using the <code>int</code> "|" operator) two or more
 * of those <code>SWT</code> style constants. The class description
 * lists the style constants that are applicable to the class.
 * Style bits are also inherited from superclasses.
 * </p>
 *
 * @param parent a composite control which will be the parent of the new instance (cannot be null)
 * @param style the style of control to construct
 *
 * @exception IllegalArgumentException <ul>
 *    <li>ERROR_NULL_ARGUMENT - if the parent is null</li>
 * </ul>
 * @exception SWTException <ul>
 *    <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the parent</li>
 *    <li>ERROR_INVALID_SUBCLASS - if this class is not an allowed subclass</li>
 * </ul>
 *
 * @see SWT#SHADOW_ETCHED_IN
 * @see SWT#SHADOW_ETCHED_OUT
 * @see SWT#SHADOW_IN
 * @see SWT#SHADOW_OUT
 * @see SWT#SHADOW_NONE
 * @see Widget#checkSubclass
 * @see Widget#getStyle
 */
public Group (Composite parent, int style) {
	super (parent, checkStyle (style));
}

static int checkStyle (int style) {
	style |= SWT.NO_FOCUS;
	/*
	* Even though it is legal to create this widget
	* with scroll bars, they serve no useful purpose
	* because they do not automatically scroll the
	* widget's client area.  The fix is to clear
	* the SWT style.
	*/
	return style & ~(SWT.H_SCROLL | SWT.V_SCROLL);
}

@Override
protected void checkSubclass () {
	if (!isValidSubclass ()) error (SWT.ERROR_INVALID_SUBCLASS);
}

@Override
long /*int*/ clientHandle () {
	return clientHandle;
}

@Override
Point computeSizeInPixels (int wHint, int hHint, boolean changed) {
	Point size = super.computeSizeInPixels(wHint, hHint, changed);
	int width;
	if(OS.GTK3){
		width = computeNativeSize (handle, SWT.DEFAULT, SWT.DEFAULT, false).x;
	}
	else{
		int x_thickness = OS.gtk_style_get_xthickness (OS.gtk_widget_get_style (handle));
		// GTK adds a LABEL_PAD and LABEL_SIDE_PAD to the label width, we also need to add
          	// the thickness of the frame border
		int minimalSizeAroundLabel = 2 * (OS.GTK_FRAME_LABEL_PAD + OS.GTK_FRAME_LABEL_SIDE_PAD + x_thickness);
		width = computeNativeSize (labelHandle, SWT.DEFAULT, SWT.DEFAULT, false) .x + minimalSizeAroundLabel;
	}
	size.x = Math.max (size.x, width);
	return size;
}
@Override
Rectangle computeTrimInPixels (int x, int y, int width, int height) {
	checkWidget();
	forceResize ();
	GtkAllocation allocation = new GtkAllocation();
	OS.gtk_widget_get_allocation (clientHandle, allocation);
	int clientX = allocation.x;
	int clientY = allocation.y;
	x -= clientX;
	y -= clientY;
	width += clientX + clientX;
	height += clientX + clientY;
	return new Rectangle (x, y, width, height);
}

@Override
Rectangle getClientAreaInPixels () {
	Rectangle clientRectangle = super.getClientAreaInPixels ();
	/*
	* Bug 453827 Child position fix.
	* SWT's calls to gtk_widget_size_allocate and gtk_widget_set_allocation
	* causes GTK+ to move the clientHandle's SwtFixed down by the size of the label.
	* These calls can come up from 'shell' and group has no control over these calls.
	*
	* This is an undesired side-effect. Client handle's x & y positions should never
	* be incremented as this is an internal sub-container.
	*
	* Note: 0 by 0 was chosen as 1 by 1 shifts controls beyond their original pos.
	* The long term fix would be to not use widget_*_allocation from higher containers
	* like shell and to not use	gtkframe in non-group widgets (e.g used in label atm).
	*/
	clientRectangle.x = 0;
	clientRectangle.y = 0;
	return clientRectangle;
}

@Override
GdkColor getContextColor () {
	if (OS.GTK_VERSION >= OS.VERSION (3, 16, 0)) {
		if (foreground != null) {
			return display.toGdkColor (foreground);
		} else {
			return display.COLOR_WIDGET_FOREGROUND;
		}
	} else {
		return super.getContextColor();
	}
}

@Override
void createHandle(int index) {
	state |= HANDLE | THEME_BACKGROUND;

	fixedHandle = OS.g_object_new (display.gtk_fixed_get_type (), 0);
	if (fixedHandle == 0) error (SWT.ERROR_NO_HANDLES);
	OS.gtk_widget_set_has_window (fixedHandle, true);

	handle = OS.gtk_frame_new (null);
	if (handle == 0) error (SWT.ERROR_NO_HANDLES);

	labelHandle = OS.gtk_label_new (null);
	if (labelHandle == 0) error (SWT.ERROR_NO_HANDLES);
	OS.g_object_ref (labelHandle);
	OS.g_object_ref_sink (labelHandle);

	clientHandle = OS.g_object_new (display.gtk_fixed_get_type (), 0);
	if (clientHandle == 0) error (SWT.ERROR_NO_HANDLES);
	/*
	 * Bug 453827 - clientHandle now has it's own window so that
	 * it can listen to events (clicking/tooltip etc.) and so that
	 * background can be drawn on it.
	 */
	OS.gtk_widget_set_has_window (clientHandle, true);

	OS.gtk_container_add (fixedHandle, handle);
	OS.gtk_container_add (handle, clientHandle);
	if ((style & SWT.SHADOW_IN) != 0) {
		OS.gtk_frame_set_shadow_type (handle, OS.GTK_SHADOW_IN);
	}
	if ((style & SWT.SHADOW_OUT) != 0) {
		OS.gtk_frame_set_shadow_type (handle, OS.GTK_SHADOW_OUT);
	}
	if ((style & SWT.SHADOW_ETCHED_IN) != 0) {
		OS.gtk_frame_set_shadow_type (handle, OS.GTK_SHADOW_ETCHED_IN);
	}
	if ((style & SWT.SHADOW_ETCHED_OUT) != 0) {
		OS.gtk_frame_set_shadow_type (handle, OS.GTK_SHADOW_ETCHED_OUT);
	}
	// In GTK 3 font description is inherited from parent widget which is not how SWT has always worked,
	// reset to default font to get the usual behavior
	if (OS.GTK3) {
		setFontDescription (defaultFont ().handle);
	}
}

@Override
int applyThemeBackground () {
	return 1;
}

@Override
void deregister () {
	super.deregister ();
	display.removeWidget (clientHandle);
	display.removeWidget (labelHandle);
}

@Override
void enableWidget (boolean enabled) {
	OS.gtk_widget_set_sensitive (labelHandle, enabled);
}

@Override
long /*int*/ eventHandle () {
	/*
	 * Bug 453827 - Group's events should be handled via it's internal
	 * fixed container (clientHandle) and not via it's top level.
	 * This makes it behave more like composite.
	 */
	return clientHandle;
}

@Override
String getNameText () {
	return getText ();
}

/**
 * Returns the receiver's text, which is the string that the
 * is used as the <em>title</em>. If the text has not previously
 * been set, returns an empty string.
 *
 * @return the text
 *
 * @exception SWTException <ul>
 *    <li>ERROR_WIDGET_DISPOSED - if the receiver has been disposed</li>
 *    <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver</li>
 * </ul>
 */
public String getText () {
	checkWidget();
	return text;
}

@Override
void hookEvents () {
	super.hookEvents();
	if (labelHandle != 0) {
		OS.g_signal_connect_closure_by_id (labelHandle, display.signalIds [MNEMONIC_ACTIVATE], 0, display.getClosure (MNEMONIC_ACTIVATE), false);
	}
}

@Override
boolean mnemonicHit (char key) {
	if (labelHandle == 0) return false;
	boolean result = super.mnemonicHit (labelHandle, key);
	if (result) setFocus ();
	return result;
}

@Override
boolean mnemonicMatch (char key) {
	if (labelHandle == 0) return false;
	return mnemonicMatch (labelHandle, key);
}

@Override
long /*int*/ parentingHandle() {
	/*
	 * Bug 453827 - Children should be attached to the internal fixed
	 * subcontainer (clienthandle) and not the top-level fixedHandle.
	 */
	return clientHandle;
}

@Override
void register () {
	super.register ();
	display.addWidget (clientHandle, this);
	display.addWidget (labelHandle, this);
}

@Override
void releaseHandle () {
	super.releaseHandle ();
	clientHandle = labelHandle = 0;
}

@Override
void releaseWidget () {
	super.releaseWidget ();
	if (labelHandle != 0) OS.g_object_unref (labelHandle);
	text = null;
}

@Override
void setBackgroundColor (GdkColor color) {
	if (OS.GTK_VERSION >= OS.VERSION(3, 16, 0)) {
		// With CSS theming we only need to set the background color
		// of the parent SwtFixed container.
		setBackgroundColor (fixedHandle, color);
		return;
	} else {
		super.setBackgroundColor (color);
		setBackgroundColor (fixedHandle, color);
		// Bug 453827 - client handle should also be painted as it's visible to the user now.
		setBackgroundColor (clientHandle, color);
	}
}

@Override
void setFontDescription (long /*int*/ font) {
	super.setFontDescription (font);
	setFontDescription (labelHandle, font);
}

@Override
void setForegroundColor (GdkColor color) {
	if (OS.GTK_VERSION >= OS.VERSION(3, 16, 0)) {
		GdkRGBA rgba = null;
		if (color != null) {
			rgba = display.toGdkRGBA (color);
		}
		/*
		 * When using CSS, setting the foreground color on an empty label
		 * widget prevents the background from being set. If a user wants
		 * to specify a foreground color before the text is set, store the
		 * color and wait until text is specified to apply it.
		 */
		if (text.isEmpty()) {
			foreground = rgba;
		} else {
			setForegroundColor (labelHandle, rgba);
			foreground = rgba;
		}
	} else {
		super.setForegroundColor (color);
		setForegroundColor(labelHandle, color);
	}
}

@Override
void setOrientation (boolean create) {
	super.setOrientation (create);
	if ((style & SWT.RIGHT_TO_LEFT) != 0 || !create) {
		int dir = (style & SWT.RIGHT_TO_LEFT) != 0 ? OS.GTK_TEXT_DIR_RTL : OS.GTK_TEXT_DIR_LTR;
		OS.gtk_widget_set_direction (labelHandle, dir);
	}
}

/**
 * Sets the receiver's text, which is the string that will
 * be displayed as the receiver's <em>title</em>, to the argument,
 * which may not be null. The string may include the mnemonic character.
 * </p>
 * Mnemonics are indicated by an '&amp;' that causes the next
 * character to be the mnemonic.  When the user presses a
 * key sequence that matches the mnemonic, focus is assigned
 * to the first child of the group. On most platforms, the
 * mnemonic appears underlined but may be emphasised in a
 * platform specific manner.  The mnemonic indicator character
 * '&amp;' can be escaped by doubling it in the string, causing
 * a single '&amp;' to be displayed.
 * </p><p>
 * Note: If control characters like '\n', '\t' etc. are used
 * in the string, then the behavior is platform dependent.
 * </p>
 * @param string the new text
 *
 * @exception IllegalArgumentException <ul>
 *    <li>ERROR_NULL_ARGUMENT - if the text is null</li>
 * </ul>
 * @exception SWTException <ul>
 *    <li>ERROR_WIDGET_DISPOSED - if the receiver has been disposed</li>
 *    <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver</li>
 * </ul>
 */
public void setText (String string) {
	checkWidget();
	if (string == null) error (SWT.ERROR_NULL_ARGUMENT);
	text = string;
	char [] chars = fixMnemonic (string);
	byte [] buffer = Converter.wcsToMbcs (chars, true);
	OS.gtk_label_set_text_with_mnemonic (labelHandle, buffer);
	if (string.length () != 0) {
		if (OS.gtk_frame_get_label_widget (handle) == 0) {
			OS.gtk_frame_set_label_widget (handle, labelHandle);
		}
	} else {
		OS.gtk_frame_set_label_widget (handle, 0);
	}
	// Set the foreground now that the text has been set
	if (OS.GTK_VERSION >= OS.VERSION (3, 16, 0)) {
		setForegroundColor (labelHandle, foreground);
	}
}

@Override
void showWidget () {
	super.showWidget ();
	if (clientHandle != 0) OS.gtk_widget_show (clientHandle);
	if (labelHandle != 0) OS.gtk_widget_show (labelHandle);
}

@Override
int setBounds(int x, int y, int width, int height, boolean move, boolean resize) {

		if (OS.GTK3) {
			// Work around for bug 470129.
			// See also https://bugzilla.gnome.org/show_bug.cgi?id=754976 :
			// GtkFrame: Attempt to allocate size of width 1 (or a small number) fails
			//
			// GtkFrame does not handle well allocating less than its minimum size
			GtkRequisition requisition = new GtkRequisition();
			OS.gtk_widget_get_preferred_size(handle, requisition, null);
			width = Math.max(requisition.width, width);
		}

	return super.setBounds(x, y, width, height, move, resize);
}

@Override
long /*int*/ paintHandle() {
	if (OS.GTK3) {
		return super.paintHandle();
	}
	else {
		long /*int*/ topHandle = topHandle ();
		/* we draw all our children on the clientHandle*/
		long /*int*/ paintHandle = clientHandle;
		while (paintHandle != topHandle) {
			if (OS.gtk_widget_get_has_window (paintHandle)) break;
			paintHandle = OS.gtk_widget_get_parent (paintHandle);
		}
		return paintHandle;
	}
}

@Override
long /*int*/ paintWindow () {
	long /*int*/ paintHandle = clientHandle;
	OS.gtk_widget_realize (paintHandle);
	return gtk_widget_get_window (paintHandle);
}

}