Unity3D Custom editor focus change with EditorGUILayout.LabelField - unity3d

I've an issue working with custom editor, my editing focus is changed without any action from my part.
Basically, this is a screen of my custom editor in a neutral state (just added empty translation entity):
And this is a screen when my focus got change without reason. As you can see, my editor detected that 2 keys was the same and notify it by a message at the top of the box, the issue is that I was actually editing the second box's "key" field, and my focus changed on the first box (highlighted blue). If I don't display the warning message, I don't have any issue so I guess it comes from there..
This is my custom editor script :
[CustomEditor(typeof(InternationalizationDatabaseSO))]
public class InternationalizationDatabaseSOEditor : Editor
{
#region Constantes
private const string ITEMS_PROPERTY_NAME = "_mItems";
private const string ITEM_CATEGORY_NAME = "_mCategory";
private const string ITEM_KEY_NAME = "_mKey";
private const string ITEM_VALUES_NAME = "_mValues";
private const string ITEM_VALUE_LANGUAGE = "_mLanguage";
private const string ITEM_VALUE_VALUE = "_mValue";
#endregion
#region Attributs
private InternationalizationDatabaseSO _mDatabase;
#endregion
#region Methods
private void OnEnable()
{
Init();
}
private void Init()
{
_mDatabase = target as InternationalizationDatabaseSO;
}
public override void OnInspectorGUI()
{
serializedObject.Update();
SerializedProperty itemsProperty = serializedObject.FindProperty(ITEMS_PROPERTY_NAME);
int arraySize = itemsProperty.arraySize;
EditorGUI.BeginDisabledGroup(false);
{
EditorGUILayout.BeginHorizontal();
{
GUILayout.FlexibleSpace();
if (OnInspectorGUIButton("+", 40, 25, Color.white, Color.green))
{
itemsProperty.arraySize++;
itemsProperty.GetArrayElementAtIndex(itemsProperty.arraySize - 1).FindPropertyRelative(ITEM_CATEGORY_NAME).stringValue = "";
itemsProperty.GetArrayElementAtIndex(itemsProperty.arraySize - 1).FindPropertyRelative(ITEM_KEY_NAME).stringValue = "";
serializedObject.ApplyModifiedProperties();
Init();
return;
}
}
EditorGUILayout.EndHorizontal();
EditorGUILayout.Space();
for(int i = 0; i < arraySize; i++)
{
if(OnInspectorGUIItem(i) == false)
{
serializedObject.ApplyModifiedProperties();
Init();
return;
}
}
}
EditorGUI.EndDisabledGroup();
serializedObject.ApplyModifiedProperties();
}
private bool OnInspectorGUIItem(int index)
{
SerializedProperty itemsProperty = serializedObject.FindProperty(ITEMS_PROPERTY_NAME);
SerializedProperty itemCategory = itemsProperty.GetArrayElementAtIndex(index).FindPropertyRelative(ITEM_CATEGORY_NAME);
SerializedProperty itemKey = itemsProperty.GetArrayElementAtIndex(index).FindPropertyRelative(ITEM_KEY_NAME);
EditorGUI.indentLevel += 1;
EditorGUILayout.BeginVertical(GUI.skin.box);
{
EditorGUILayout.Space();
EditorGUILayout.BeginHorizontal();
{
EditorGUILayout.BeginVertical();
{
if(KeyAlreadyExist(index, itemKey.stringValue))
{
OnInspectorGUIText("Key already exists", 12, Color.red, FontStyle.Bold, false);
}
OnInspectorGUIText("Key : " + itemKey.stringValue, 12, FontStyle.Normal, false);
}
EditorGUILayout.EndVertical();
GUILayout.FlexibleSpace();
if(OnInspectorGUIButton("-", 40, 25, Color.white, Color.red))
{
itemCategory.stringValue = "";
itemKey.stringValue = "";
itemsProperty.DeleteArrayElementAtIndex(index);
return false;
}
}
EditorGUILayout.EndHorizontal();
EditorGUILayout.Space();
EditorGUILayout.BeginVertical();
{
GUIStyle style = EditorStyles.foldout;
style.fontSize = 15;
style.fontStyle = FontStyle.Bold;
itemCategory.isExpanded = EditorGUILayout.Foldout(itemCategory.isExpanded, "General informations", style);
if(itemCategory.isExpanded)
{
EditorGUILayout.Space();
EditorGUILayout.PropertyField(itemCategory, new GUIContent("Category"));
EditorGUILayout.PropertyField(itemKey, new GUIContent("Key"));
}
if(OnInspectorGUIItemLanguage(index, itemsProperty.GetArrayElementAtIndex(index)) == false)
{
return false;
}
}
EditorGUILayout.EndVertical();
}
EditorGUILayout.EndVertical();
EditorGUI.indentLevel -= 1;
return true;
}
private bool OnInspectorGUIItemLanguage(int index, SerializedProperty propertyItem)
{
EditorGUILayout.BeginVertical();
{
GUIStyle style = EditorStyles.foldout;
style.fontSize = 15;
style.normal.textColor = Color.black;
style.fontStyle = FontStyle.Bold;
SerializedProperty itemValues = propertyItem.FindPropertyRelative(ITEM_VALUES_NAME);
itemValues.isExpanded = EditorGUILayout.Foldout(itemValues.isExpanded, "Languages informations", style);
if(itemValues.isExpanded)
{
EditorGUILayout.Space();
EditorGUILayout.BeginVertical();
{
EditorGUILayout.BeginHorizontal();
{
int nbTranslation = itemValues.arraySize;
EditorGUILayout.LabelField("Nb translation : " + nbTranslation);
GUILayout.FlexibleSpace();
if (OnInspectorGUIButton("+", 20, 20, Color.white, Color.green))
{
itemValues.arraySize++;
itemValues.GetArrayElementAtIndex(itemValues.arraySize - 1).FindPropertyRelative(ITEM_VALUE_LANGUAGE).intValue = 0;
itemValues.GetArrayElementAtIndex(itemValues.arraySize - 1).FindPropertyRelative(ITEM_VALUE_VALUE).stringValue = "";
return false;
}
}
EditorGUILayout.EndHorizontal();
EditorGUILayout.Space();
if (itemValues.arraySize > 0)
{
string translatedLanguages = "{";
foreach (InternationalizationDatabaseItemLanguage item in _mDatabase.Items[index].Values)
{
translatedLanguages += item.Language.ToString() + ", ";
}
if (translatedLanguages.Length > 2)
{
translatedLanguages = translatedLanguages.Remove(translatedLanguages.Length - 2);
}
translatedLanguages += "}";
//EditorStyles.label.stretchHeight = true;
EditorStyles.label.wordWrap = true;
EditorGUILayout.LabelField("Translated : \n" + translatedLanguages);
EditorGUILayout.Space();
for (int i = 0; i < itemValues.arraySize; i++)
{
EditorGUILayout.BeginVertical(GUI.skin.box);
{
EditorGUILayout.Space();
InternationalizationDatabaseItemLanguage item = _mDatabase.Items[index].Values[i];
SerializedProperty propLanguage = itemValues.GetArrayElementAtIndex(i).FindPropertyRelative(ITEM_VALUE_LANGUAGE);
SerializedProperty propValue = itemValues.GetArrayElementAtIndex(i).FindPropertyRelative(ITEM_VALUE_VALUE);
EditorGUILayout.BeginHorizontal();
{
if (LanguageAlreadyExist(index, i, _mDatabase.Items[index].Values[i].Language))
{
OnInspectorGUIText("Warning language translation already exist", 12, Color.red, FontStyle.Bold, false);
}
GUILayout.FlexibleSpace();
if (OnInspectorGUIButton("-", 20, 20, Color.white, Color.red))
{
itemValues.DeleteArrayElementAtIndex(i);
return false;
}
}
EditorGUILayout.EndHorizontal();
EditorGUILayout.Space();
EditorGUILayout.PropertyField(propLanguage, new GUIContent("Language"));
EditorGUILayout.PrefixLabel("Translation");
propValue.stringValue = EditorGUILayout.TextArea(propValue.stringValue, GUILayout.Height(80));
}
EditorGUILayout.Space();
EditorGUILayout.EndVertical();
EditorGUILayout.Space();
}
}
}
EditorGUILayout.EndVertical();
}
}
EditorGUILayout.EndVertical();
EditorGUILayout.Space();
return true;
}
private bool KeyAlreadyExist(int currentIndex, string key)
{
for(int i = 0; i < _mDatabase.Items.Count; i++)
{
InternationalizationDatabaseItem item = _mDatabase.Items[i];
if(currentIndex != i && item.Key == key && string.IsNullOrEmpty(key) == false)
{
return true;
}
}
return false;
}
private bool LanguageAlreadyExist(int indexInDatabase, int currentIndex, SystemLanguage language)
{
for (int i = 0; i < _mDatabase.Items[indexInDatabase].Values.Count; i++)
{
InternationalizationDatabaseItemLanguage item = _mDatabase.Items[indexInDatabase].Values[i];
if (currentIndex != i && item.Language == language)
{
return true;
}
}
return false;
}
private void OnInspectorGUIText(string text, FontStyle fontStyle, bool prefixLabel)
{
GUIStyle style = new GUIStyle();
style.fontStyle = fontStyle;
style.wordWrap = true;
if (prefixLabel)
{
EditorGUILayout.PrefixLabel(text, GUIStyle.none, style);
}
else
{
EditorGUILayout.LabelField(text, style);
}
}
private void OnInspectorGUIText(string text, int fontSize, FontStyle fontStyle, bool prefixLabel)
{
GUIStyle style = new GUIStyle();
style.fontSize = fontSize;
style.fontStyle = fontStyle;
style.wordWrap = true;
if (prefixLabel)
{
EditorGUILayout.PrefixLabel(text, GUIStyle.none, style);
}
else
{
EditorGUILayout.LabelField(text, style);
}
}
private void OnInspectorGUIText(string text, int fontSize, Color textColor, FontStyle fontStyle, bool prefixLabel)
{
GUIStyle style = new GUIStyle();
style.fontSize = fontSize;
style.normal.textColor = textColor;
style.fontStyle = fontStyle;
style.wordWrap = true;
if(prefixLabel)
{
EditorGUILayout.PrefixLabel(text, GUIStyle.none, style);
}
else
{
EditorGUILayout.LabelField(text, style);
}
}
private bool OnInspectorGUIButton(string label, int width, int height, Color textColor, Color backgroundColor)
{
Color saveColor = GUI.backgroundColor;
GUILayoutOption[] options = { GUILayout.Width(width), GUILayout.Height(height) };
GUIStyle style = new GUIStyle(GUI.skin.button);
style.normal.textColor = textColor;
GUI.backgroundColor = backgroundColor;
bool pressed = GUILayout.Button(label, style, options);
GUI.backgroundColor = saveColor;
return pressed;
}
#endregion
}
Have you any suggestion ? Thanks
Have a nice day.

Are you sure you are not sharing reference to the same property in both boxes ?

Ok finally figured it out, I mean, I'm not still totally certain why it happens, but found a workaround thanks to : https://forum.unity.com/threads/editor-gui-inputfield-loses-focus-when-gui-updates.542147/
Basically, I'm just displaying always the LabelField, but if there is no error, I simply set the errorMessage to an empty string

Related

Xamarin form: Why there is a gap in between the cells

I have a custom view in side the item on the right highlighted in black.
The each view cell has a big gap because of the black custom view. This black view is a grid which was added in the bindingContextChanged function.
public partial class ShiftTemplate : ViewCell
{
public ShiftTemplate()
{
InitializeComponent();
}
}
public class ShiftView : ContentView
{
protected override void OnBindingContextChanged()
{
base.OnBindingContextChanged();
var model = BindingContext as StaffShiftViewModel;
var grid = new Grid();
var shiftCount = 0;
var index = 0;
grid.ColumnDefinitions.Add(new ColumnDefinition() { Width = GridLength.Star });
grid.ColumnDefinitions.Add(new ColumnDefinition() { Width = GridLength.Star });
foreach (var shift in model.Shifts)
{
grid.RowDefinitions.Add(new RowDefinition() { Height = GridLength.Auto });
grid.RowDefinitions.Add(new RowDefinition() { Height = GridLength.Auto });
grid.RowDefinitions.Add(new RowDefinition() { Height = GridLength.Auto });
var timeLabel = new Label
{
Text = shift.Time,
VerticalTextAlignment = TextAlignment.Center,
HorizontalTextAlignment = TextAlignment.End
};
var clockButton = new Button
{
Text = shift.ClockStatus,
VerticalOptions = LayoutOptions.Center,
HorizontalOptions = LayoutOptions.Start,
Command = shift.OnClockingPopupCommand
};
var binding = new Binding();
binding.Source = shift;
binding.Path = nameof(shift.ClockStatus);
binding.Mode = BindingMode.OneWay;
clockButton.SetBinding(Button.TextProperty, binding);
var line = new BoxView { HorizontalOptions = LayoutOptions.FillAndExpand, VerticalOptions = LayoutOptions.Center, HeightRequest = 1, BackgroundColor = Color.Gray };
grid.Children.Add(timeLabel, 0, 1, shiftCount, shiftCount+1);
grid.Children.Add(clockButton, 1, 2, shiftCount, shiftCount+1);
index += 1;
if (index < model.Shifts.Count)
grid.Children.Add(line, 0, 2, shiftCount + 1, shiftCount + 2);
shiftCount+=2;
}
Content = grid;
ForceLayout();
}
}

Unity2D: Enemy ignoring collision when moving back down

My game is a 2D top down platform, I have an zombie enemy that moves up and down the stage, I can place obstacles (such as a create) in its way to stop the enemy, the enemy has the ability to dodge these obstacles at any random moment. If the enemy collided with the create, the enemy will stop its movement to break the create. Once the create is broken, the enemy will continue to moving up, hit point B and then will move back down the stage. My Problem: If the enemy were to dodge left (for example) and then continues to move down and passes another create, the enemy will ignore collision and the function for it to stop and break that create. How do I fix this issue?
public bool hitCollider = false;
public bool hitCollider2 = false;
public bool canMove = true;
public bool moveDown = false;
public bool isMovingUp = true;
public bool isMovingDown = false;
public bool isSomethere = false;
public bool ifMoving;
public float velocidadMax;
public float xMax;
public float xMin;
public float delay;
public float x;
private float tiempo;
public float countDown, countUp, startTime;
void Start () {
Bcol = GetComponent<BoxCollider2D> ();
Bcol.isTrigger = true;
isMovingUp = true;
rigid = GetComponent <Rigidbody2D> ();
velocidadMax = 0.12f;
x = velocidadMax;
InvokeRepeating ("turnFalse", startTime, countDown); // changing lanes
InvokeRepeating ("turnTrue", 0, countUp); // moving up or down
ifMoving = true;
movedownSpeed = -4f;
moveupSpeed = 4f;
hascollidedwHouse = false;
}
void Update () {
if (moveDown == false) {
rigid.velocity = new Vector2 (0, moveupSpeed); // moving up
if (ifMoving == true) {
//irrelevant - don't need to know code here!
} else if (ifMoving == false) {
movedownSpeed = -4;
moveupSpeed = 0;
Move ();
}
}
if (moveDown == true) {
if (hitMascot2 == true) {
} else if (hitMascot2 == false) {
movingDown = true;
Bcol.isTrigger = true;
StartCoroutine (waitMove ());
StartCoroutine (destroyObj ());
}
}
if (isMovingDown == true) {
Debug.Log ("MovingDown");
Bcol.isTrigger = true;
if (canMove == false) {
Debug.Log ("is False" + canMove);
moveupSpeed = 4f;
}
hitCollider = false;
hitCollider2 = false;
}
if (hitCollider == true) {
StartCoroutine (wait ());
Debug.Log ("I HAVE COLLIDED");
if (canMove == true) {
movedownSpeed = 0f;
}
if (canMove == false) {
movedownSpeed = -4f;
}
moveupSpeed = 0f;
}
if (hitCollider2 == true) {
StartCoroutine (wait2 ());
Debug.Log ("I HAVE COLLIDED");
if (canMove == true) {
movedownSpeed = 0f;
}
if (canMove == false) {
movedownSpeed = -4f;
}
moveupSpeed = 0f;
}
}
void OnTriggerEnter2D (Collider2D col) {
if (col.tag == "objects") {
hitCollider = true;
woodBox = true;
canMove = false;
moveDown = false;
xMax = 0;
xMin = 0;
if (hascollidedwHouse == true) {
moveDown = false;
isMovingDown = false;
movedownSpeed = 0;
moveupSpeed = 0;
hitCollider = false;
ifMoving = false;
xMax = 0;
xMin = 0;
StartCoroutine (waitDown ());
}
}
if (col.tag == "objects2") {
hitCollider2 = true;
metalBox = true;
canMove = false;
hitwoodenC = false;
hitmetalC = true;
moveDown = false;
xMax = 0;
xMin = 0;
if (hascollidedwHouse == true) {
moveDown = false;
isMovingDown = false;
movedownSpeed = 0;
moveupSpeed = 0;
ifMoving = false;
hitCollider2 = false;
xMax = 0;
xMin = 0;
StartCoroutine (waitDown2 ());
}
}
if (col.tag == "pointB") {
if (ifMoving == false) {
moveupSpeed = 0;
movedownSpeed = -4;
} else if (ifMoving == true) {
moveupSpeed = 0;
movedownSpeed = -4;
}
Debug.Log ("Collided");
moveDown = true;
isMovingDown = true;
isMovingUp = false;
canMove = false;
hascollidedwHouse = true;
}
void Move () {
if (isSomethere == false) {
if (isMovingUp == true) {
tiempo += Time.deltaTime;
if (transform.localPosition.x < xMin) {
x = Random.Range (0.0f, velocidadMax);
x = velocidadMax;
tiempo = 0.0f;
Debug.Log ("Left");
}
if (tiempo > 1.0f) { //1.0 0.3
x = -velocidadMax;
tiempo = 0.0f;
Debug.Log ("Right");
}
transform.localPosition = new Vector3 (transform.localPosition.x + x, transform.localPosition.y);
}
} else if (isSomethere == true) {
movedownSpeed = -4;
moveupSpeed = 4;
if (iSPdeath == true) {
movedownSpeed = 0;
moveupSpeed = 0;
}
}
}
void turnFalse ()
{
if( hitCollider == false) {
ifMoving = false; // moves left and right
}
if( hitCollider2 == false) {
ifMoving = false; // moves left and right
}
}
void turnTrue() {
if( hitCollider == false) {
ifMoving = true; // moves up and down
}
if( hitCollider2 == false) {
ifMoving = true; // moves up and down
}
}
IEnumerator wait() {
yield return new WaitForSeconds (2.5f);
hitCollider = false;
if (isMovingUp == true) {
canMove = true;
}
if (isMovingUp == false) {
canMove = false;
moveupSpeed = 0f;
movedownSpeed = -4f;
}
if (canMove == true) {
moveupSpeed = 4f;
}
}
IEnumerator wait2() {
yield return new WaitForSeconds (5.2f);
hitCollider = false;
if (isMovingUp == true) {
canMove = true;
}
if (isMovingUp == false) {
canMove = false;
moveupSpeed = 0f;
movedownSpeed = -4f;
}
if (canMove == true) {
moveupSpeed = 4f;
}
}
IEnumerator waitDown() {
yield return new WaitForSeconds (2.5f);
movedownSpeed = -4f;
moveupSpeed = 0f;
moveDown = true;
}
IEnumerator waitDown2() {
yield return new WaitForSeconds (5.2f);
movedownSpeed = -4f;
moveupSpeed = 0f;
moveDown = true;
}
}

Unity Fade delay when game ends

I'm fairly new at Unity and i'm trying to making a game.
I want to have an subtitle fading in when you're at the end of the game. This start when you hit a button.
But when I code a image that I fadein, it plays it directly when you start the game.
Do you guys know a solution?
#pragma strict
private var guiShow : boolean = false;
var car : GameObject;
var rayLength = 10;
var guiObject : GUITexture;
var fadeTime = 1.0;
enum Fade {In, Out}
var fadesubtitles : boolean = false;
function Update ()
{
var hit : RaycastHit;
var fwd = transform.TransformDirection(Vector3.forward);
if(Physics.Raycast(transform.position, fwd, hit, rayLength))
{
if(hit.collider.gameObject.tag == "car")
{
guiShow = true;
if(Input.GetKeyDown("e"))
{
guiShow = false;
}
else if(Input.GetKeyDown("e"))
{
guiShow = false;
}
}
}
else
{
guiShow = false;
}
}
function OnGUI()
{
if(guiShow == true)
{
GUI.Box(Rect(Screen.width / 2, Screen.height / 2, 150, 25), "Press F to escape");
if(Input.GetKeyDown("f")){
fadesubtitles = true;
}
}
}
if (fadesubtitles == true){
yield FadeGUITexture(guiObject, fadeTime, Fade.In);
yield WaitForSeconds(3.0);
yield FadeGUITexture(guiObject, fadeTime, Fade.Out);
}
function FadeGUITexture (guiObject : GUITexture, timer : float, fadeType : Fade) {
if (subtitles == true){
var start = fadeType == Fade.In? 0.0 : 1.0;
var end = fadeType == Fade.In? 1.0 : 0.0;
var i = 0.0;
var step = 1.0/timer;
while (i < 1.0) {
i += step * Time.deltaTime;
guiObject.color.a = Mathf.Lerp(start, end, i)*.5;
yield;
}
}
}
I'd start your game object in the 'disabled' state (uncheck it in the inspector). Then at then end of the game, have some code that enables it.
You can use iTween.
FadeFrom(GameObject target, Hashtable args)
Example:
iTween.FadeFrom(gameObject, iTween.Hash("alpha", 0f, "amount", 1f, "time", 2f));

select and deselect object in unity3D

i am making a game in which i am using is-clicked function when i click the object the letter written on it displayed now i want that when i clicked the same object again the word disappear... now how can i do that?
#pragma strict
static var nextPos = 200;
var word: String;
var sel: String;
var isClicked : boolean=false;
var xpos: float = 200;
function OnMouseDown()
{
if (!isClicked) {
isClicked = true;
xpos = nextPos;
nextPos += 8;
}
}
function OnGUI()
{
if (gameObject.name == "Sphere(Clone)" && isClicked )
{
GUI.Label(new Rect(xpos,260,400,100), "A");
}
else if (gameObject.name == "Sphere 1(Clone)" && isClicked )
{
GUI.Label(new Rect(xpos,260,400,100), "B");
}
else if (gameObject.name == "Sphere 2(Clone)" && isClicked )
{
GUI.Label(new Rect(xpos,260,400,100), "C");
}
else if (gameObject.name == "Sphere 3(Clone)" && isClicked )
{
GUI.Label(new Rect(xpos,260,400,100), "D");
}
}
write in OnMouseDown
else if(isClicked)
{
isClicked = false;
// do your xpos stuff here
}

Is there a custom Label widget which supports animated GIF?

I am trying to write a custom Label widget which supports animated GIF, but I found it's hard for me. Is there already such a widget available for use?
Edit---------------------------------------------------------------------------------
When I try to use GifCLabel class, it works fine with a gif picture(animated), but if I try to set a static png picture to it when the animation thread is running, the png picture will not be shown, but a frame of the animated gif is shown, here is my code :
public PageDemo(Shell parentShell) {
super(parentShell);
Composite topComp = new Composite(parentShell, SWT.NONE);
topComp.setLayout(new FormLayout());
final GifCLabel gl = new GifCLabel(topComp, SWT.CENTER);
gl.setText("some message");
gl.setGifImage("c://loading.gif");
Display.getCurrent().timerExec(5000, new Runnable(){
#Override
public void run() {
// gl.setGifImage("c:\\filter.png"); // also not work
gl.setImage(SWTResourceManager.getImage("c:\\filter.png"));
}
});
}
Bug fix--------------------------------------------------------------------------------
I think Sorceror's code is good, but there seems is a little bug:
public void run() {
while (run) {
int delayTime = loader.data[imageNumber].delayTime;
try {
Thread.sleep(delayTime * 10);
} catch (InterruptedException e) {
e.printStackTrace();
}
if (!GifCLabel.this.isDisposed()) {
// if a asynchronous thread is running, this new runnable will be queued
GifCLabel.this.getDisplay().asyncExec(new Runnable() {
public void run() {
if(!run){
return;
}
if (!GifCLabel.this.isDisposed()) {
imageNumber = imageNumber == loader.data.length - 1 ? 0 : imageNumber + 1;
if (!GifCLabel.this.image.isDisposed())
GifCLabel.this.image.dispose();
ImageData nextFrameData = loader.data[imageNumber];
System.out.println("set to frame " + imageNumber);
GifCLabel.this.image = new Image(GifCLabel.this.getDisplay(), nextFrameData);
GifCLabel.this.redraw();
} else
stopRunning();
}
});
} else
stopRunning();
}
}
notice what I added in above :
if(!run){
return;
}
In the article Taking a look at SWT Images - Animation part is whole source code of gif animation for almost any purpose.. It didn't help?
EDIT
So I did the job, and here is a GifCLabel class for you which supports gif animation.. It's derived from SWT CLabel class, see setGifImage(String path), setGifImage(InputStream inputStream) methods and GifThread private class.
import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.InputStream;
import org.eclipse.swt.*;
import org.eclipse.swt.widgets.*;
import org.eclipse.swt.graphics.*;
import org.eclipse.swt.events.*;
import org.eclipse.swt.accessibility.*;
/**
* <p><b>This class supports gif animation in label and is derived from {#link GifCLabel} SWT class (see {#link #setGifImage(InputStream)} or {#link #setGifImage(String)})</b><br />
* <b>Changes by Sorceror, (a)sync.exec(...) call fix by YAMaiDie</b></p>
*/
public class GifCLabel extends Canvas {
/** Gap between icon and text */
private static final int GAP = 5;
/** Left and right margins */
private static final int DEFAULT_MARGIN = 3;
/** a string inserted in the middle of text that has been shortened */
private static final String ELLIPSIS = "..."; //$NON-NLS-1$ // could use the ellipsis glyph on some platforms "\u2026"
/** the alignment. Either CENTER, RIGHT, LEFT. Default is LEFT*/
private int align = SWT.LEFT;
private int leftMargin = DEFAULT_MARGIN;
private int topMargin = DEFAULT_MARGIN;
private int rightMargin = DEFAULT_MARGIN;
private int bottomMargin = DEFAULT_MARGIN;
private String text;
private Image image;
private String appToolTipText;
private boolean ignoreDispose;
private Image backgroundImage;
private Color[] gradientColors;
private int[] gradientPercents;
private boolean gradientVertical;
private Color background;
private GifThread thread = null;
private static int DRAW_FLAGS = SWT.DRAW_MNEMONIC | SWT.DRAW_TAB | SWT.DRAW_TRANSPARENT | SWT.DRAW_DELIMITER;
public GifCLabel(Composite parent, int style) {
super(parent, checkStyle(style));
if ((style & (SWT.CENTER | SWT.RIGHT)) == 0) style |= SWT.LEFT;
if ((style & SWT.CENTER) != 0) align = SWT.CENTER;
if ((style & SWT.RIGHT) != 0) align = SWT.RIGHT;
if ((style & SWT.LEFT) != 0) align = SWT.LEFT;
addPaintListener(new PaintListener() {
public void paintControl(PaintEvent event) {
onPaint(event);
}
});
addTraverseListener(new TraverseListener() {
public void keyTraversed(TraverseEvent event) {
if (event.detail == SWT.TRAVERSE_MNEMONIC) {
onMnemonic(event);
}
}
});
addListener(SWT.Dispose, new Listener() {
public void handleEvent(Event event) {
onDispose(event);
}
});
initAccessible();
}
private static int checkStyle (int style) {
if ((style & SWT.BORDER) != 0) style |= SWT.SHADOW_IN;
int mask = SWT.SHADOW_IN | SWT.SHADOW_OUT | SWT.SHADOW_NONE | SWT.LEFT_TO_RIGHT | SWT.RIGHT_TO_LEFT;
style = style & mask;
return style |= SWT.NO_FOCUS | SWT.DOUBLE_BUFFERED;
}
public Point computeSize(int wHint, int hHint, boolean changed) {
checkWidget();
Point e = getTotalSize(image, text);
if (wHint == SWT.DEFAULT){
e.x += leftMargin + rightMargin;
} else {
e.x = wHint;
}
if (hHint == SWT.DEFAULT) {
e.y += topMargin + bottomMargin;
} else {
e.y = hHint;
}
return e;
}
private void drawBevelRect(GC gc, int x, int y, int w, int h, Color topleft, Color bottomright) {
gc.setForeground(bottomright);
gc.drawLine(x+w, y, x+w, y+h);
gc.drawLine(x, y+h, x+w, y+h);
gc.setForeground(topleft);
gc.drawLine(x, y, x+w-1, y);
gc.drawLine(x, y, x, y+h-1);
}
char _findMnemonic (String string) {
if (string == null) return '\0';
int index = 0;
int length = string.length ();
do {
while (index < length && string.charAt (index) != '&') index++;
if (++index >= length) return '\0';
if (string.charAt (index) != '&') return Character.toLowerCase (string.charAt (index));
index++;
} while (index < length);
return '\0';
}
public int getAlignment() {
//checkWidget();
return align;
}
public int getBottomMargin() {
//checkWidget();
return bottomMargin;
}
public Image getImage() {
//checkWidget();
return image;
}
public int getLeftMargin() {
//checkWidget();
return leftMargin;
}
public int getRightMargin() {
//checkWidget();
return rightMargin;
}
private Point getTotalSize(Image image, String text) {
Point size = new Point(0, 0);
if (image != null) {
Rectangle r = image.getBounds();
size.x += r.width;
size.y += r.height;
}
GC gc = new GC(this);
if (text != null && text.length() > 0) {
Point e = gc.textExtent(text, DRAW_FLAGS);
size.x += e.x;
size.y = Math.max(size.y, e.y);
if (image != null) size.x += GAP;
} else {
size.y = Math.max(size.y, gc.getFontMetrics().getHeight());
}
gc.dispose();
return size;
}
public int getStyle () {
int style = super.getStyle();
switch (align) {
case SWT.RIGHT: style |= SWT.RIGHT; break;
case SWT.CENTER: style |= SWT.CENTER; break;
case SWT.LEFT: style |= SWT.LEFT; break;
}
return style;
}
public String getText() {
//checkWidget();
return text;
}
public String getToolTipText () {
checkWidget();
return appToolTipText;
}
public int getTopMargin() {
//checkWidget();
return topMargin;
}
private void initAccessible() {
Accessible accessible = getAccessible();
accessible.addAccessibleListener(new AccessibleAdapter() {
public void getName(AccessibleEvent e) {
e.result = getText();
}
public void getHelp(AccessibleEvent e) {
e.result = getToolTipText();
}
public void getKeyboardShortcut(AccessibleEvent e) {
char mnemonic = _findMnemonic(GifCLabel.this.text);
if (mnemonic != '\0') {
e.result = "Alt+"+mnemonic; //$NON-NLS-1$
}
}
});
accessible.addAccessibleControlListener(new AccessibleControlAdapter() {
public void getChildAtPoint(AccessibleControlEvent e) {
e.childID = ACC.CHILDID_SELF;
}
public void getLocation(AccessibleControlEvent e) {
Rectangle rect = getDisplay().map(getParent(), null, getBounds());
e.x = rect.x;
e.y = rect.y;
e.width = rect.width;
e.height = rect.height;
}
public void getChildCount(AccessibleControlEvent e) {
e.detail = 0;
}
public void getRole(AccessibleControlEvent e) {
e.detail = ACC.ROLE_LABEL;
}
public void getState(AccessibleControlEvent e) {
e.detail = ACC.STATE_READONLY;
}
});
}
void onDispose(Event event) {
/* make this handler run after other dispose listeners */
if (ignoreDispose) {
ignoreDispose = false;
return;
}
ignoreDispose = true;
notifyListeners (event.type, event);
event.type = SWT.NONE;
gradientColors = null;
gradientPercents = null;
backgroundImage = null;
text = null;
image = null;
appToolTipText = null;
}
void onMnemonic(TraverseEvent event) {
char mnemonic = _findMnemonic(text);
if (mnemonic == '\0') return;
if (Character.toLowerCase(event.character) != mnemonic) return;
Composite control = this.getParent();
while (control != null) {
Control [] children = control.getChildren();
int index = 0;
while (index < children.length) {
if (children [index] == this) break;
index++;
}
index++;
if (index < children.length) {
if (children [index].setFocus ()) {
event.doit = true;
event.detail = SWT.TRAVERSE_NONE;
}
}
control = control.getParent();
}
}
void onPaint(PaintEvent event) {
Rectangle rect = getClientArea();
if (rect.width == 0 || rect.height == 0) return;
boolean shortenText = false;
String t = text;
Image img = image;
int availableWidth = Math.max(0, rect.width - (leftMargin + rightMargin));
Point extent = getTotalSize(img, t);
if (extent.x > availableWidth) {
img = null;
extent = getTotalSize(img, t);
if (extent.x > availableWidth) {
shortenText = true;
}
}
GC gc = event.gc;
String[] lines = text == null ? null : splitString(text);
// shorten the text
if (shortenText) {
extent.x = 0;
for(int i = 0; i < lines.length; i++) {
Point e = gc.textExtent(lines[i], DRAW_FLAGS);
if (e.x > availableWidth) {
lines[i] = shortenText(gc, lines[i], availableWidth);
extent.x = Math.max(extent.x, getTotalSize(null, lines[i]).x);
} else {
extent.x = Math.max(extent.x, e.x);
}
}
if (appToolTipText == null) {
super.setToolTipText(text);
}
} else {
super.setToolTipText(appToolTipText);
}
// determine horizontal position
int x = rect.x + leftMargin;
if (align == SWT.CENTER) {
x = (rect.width - extent.x)/2;
}
if (align == SWT.RIGHT) {
x = rect.width - rightMargin - extent.x;
}
// draw a background image behind the text
try {
if (backgroundImage != null) {
// draw a background image behind the text
Rectangle imageRect = backgroundImage.getBounds();
// tile image to fill space
gc.setBackground(getBackground());
gc.fillRectangle(rect);
int xPos = 0;
while (xPos < rect.width) {
int yPos = 0;
while (yPos < rect.height) {
gc.drawImage(backgroundImage, xPos, yPos);
yPos += imageRect.height;
}
xPos += imageRect.width;
}
} else if (gradientColors != null) {
// draw a gradient behind the text
final Color oldBackground = gc.getBackground();
if (gradientColors.length == 1) {
if (gradientColors[0] != null) gc.setBackground(gradientColors[0]);
gc.fillRectangle(0, 0, rect.width, rect.height);
} else {
final Color oldForeground = gc.getForeground();
Color lastColor = gradientColors[0];
if (lastColor == null) lastColor = oldBackground;
int pos = 0;
for (int i = 0; i < gradientPercents.length; ++i) {
gc.setForeground(lastColor);
lastColor = gradientColors[i + 1];
if (lastColor == null) lastColor = oldBackground;
gc.setBackground(lastColor);
if (gradientVertical) {
final int gradientHeight = (gradientPercents[i] * rect.height / 100) - pos;
gc.fillGradientRectangle(0, pos, rect.width, gradientHeight, true);
pos += gradientHeight;
} else {
final int gradientWidth = (gradientPercents[i] * rect.width / 100) - pos;
gc.fillGradientRectangle(pos, 0, gradientWidth, rect.height, false);
pos += gradientWidth;
}
}
if (gradientVertical && pos < rect.height) {
gc.setBackground(getBackground());
gc.fillRectangle(0, pos, rect.width, rect.height - pos);
}
if (!gradientVertical && pos < rect.width) {
gc.setBackground(getBackground());
gc.fillRectangle(pos, 0, rect.width - pos, rect.height);
}
gc.setForeground(oldForeground);
}
gc.setBackground(oldBackground);
} else {
if (background != null || (getStyle() & SWT.DOUBLE_BUFFERED) == 0) {
gc.setBackground(getBackground());
gc.fillRectangle(rect);
}
}
} catch (SWTException e) {
if ((getStyle() & SWT.DOUBLE_BUFFERED) == 0) {
gc.setBackground(getBackground());
gc.fillRectangle(rect);
}
}
// draw border
int style = getStyle();
if ((style & SWT.SHADOW_IN) != 0 || (style & SWT.SHADOW_OUT) != 0) {
paintBorder(gc, rect);
}
Rectangle imageRect = null;
int lineHeight = 0, textHeight = 0, imageHeight = 0;
if (img != null) {
imageRect = img.getBounds();
imageHeight = imageRect.height;
}
if (lines != null) {
lineHeight = gc.getFontMetrics().getHeight();
textHeight = lines.length * lineHeight;
}
int imageY = 0, midPoint = 0, lineY = 0;
if (imageHeight > textHeight ) {
if (topMargin == DEFAULT_MARGIN && bottomMargin == DEFAULT_MARGIN) imageY = rect.y + (rect.height - imageHeight) / 2;
else imageY = topMargin;
midPoint = imageY + imageHeight/2;
lineY = midPoint - textHeight / 2;
}
else {
if (topMargin == DEFAULT_MARGIN && bottomMargin == DEFAULT_MARGIN) lineY = rect.y + (rect.height - textHeight) / 2;
else lineY = topMargin;
midPoint = lineY + textHeight/2;
imageY = midPoint - imageHeight / 2;
}
// draw the image
if (img != null) {
gc.drawImage(img, 0, 0, imageRect.width, imageHeight,
x, imageY, imageRect.width, imageHeight);
x += imageRect.width + GAP;
extent.x -= imageRect.width + GAP;
}
// draw the text
if (lines != null) {
gc.setForeground(getForeground());
for (int i = 0; i < lines.length; i++) {
int lineX = x;
if (lines.length > 1) {
if (align == SWT.CENTER) {
int lineWidth = gc.textExtent(lines[i], DRAW_FLAGS).x;
lineX = x + Math.max(0, (extent.x - lineWidth) / 2);
}
if (align == SWT.RIGHT) {
int lineWidth = gc.textExtent(lines[i], DRAW_FLAGS).x;
lineX = Math.max(x, rect.x + rect.width - rightMargin - lineWidth);
}
}
gc.drawText(lines[i], lineX, lineY, DRAW_FLAGS);
lineY += lineHeight;
}
}
}
private void paintBorder(GC gc, Rectangle r) {
Display disp= getDisplay();
Color c1 = null;
Color c2 = null;
int style = getStyle();
if ((style & SWT.SHADOW_IN) != 0) {
c1 = disp.getSystemColor(SWT.COLOR_WIDGET_NORMAL_SHADOW);
c2 = disp.getSystemColor(SWT.COLOR_WIDGET_HIGHLIGHT_SHADOW);
}
if ((style & SWT.SHADOW_OUT) != 0) {
c1 = disp.getSystemColor(SWT.COLOR_WIDGET_LIGHT_SHADOW);
c2 = disp.getSystemColor(SWT.COLOR_WIDGET_NORMAL_SHADOW);
}
if (c1 != null && c2 != null) {
gc.setLineWidth(1);
drawBevelRect(gc, r.x, r.y, r.width-1, r.height-1, c1, c2);
}
}
public void setAlignment(int align) {
checkWidget();
if (align != SWT.LEFT && align != SWT.RIGHT && align != SWT.CENTER) {
SWT.error(SWT.ERROR_INVALID_ARGUMENT);
}
if (this.align != align) {
this.align = align;
redraw();
}
}
public void setBackground (Color color) {
super.setBackground (color);
// Are these settings the same as before?
if (backgroundImage == null &&
gradientColors == null &&
gradientPercents == null) {
if (color == null) {
if (background == null) return;
} else {
if (color.equals(background)) return;
}
}
background = color;
backgroundImage = null;
gradientColors = null;
gradientPercents = null;
redraw ();
}
public void setBackground(Color[] colors, int[] percents) {
setBackground(colors, percents, false);
}
public void setBackground(Color[] colors, int[] percents, boolean vertical) {
checkWidget();
if (colors != null) {
if (percents == null || percents.length != colors.length - 1) {
SWT.error(SWT.ERROR_INVALID_ARGUMENT);
}
if (getDisplay().getDepth() < 15) {
// Don't use gradients on low color displays
colors = new Color[] {colors[colors.length - 1]};
percents = new int[] { };
}
for (int i = 0; i < percents.length; i++) {
if (percents[i] < 0 || percents[i] > 100) {
SWT.error(SWT.ERROR_INVALID_ARGUMENT);
}
if (i > 0 && percents[i] < percents[i-1]) {
SWT.error(SWT.ERROR_INVALID_ARGUMENT);
}
}
}
// Are these settings the same as before?
final Color background = getBackground();
if (backgroundImage == null) {
if ((gradientColors != null) && (colors != null) &&
(gradientColors.length == colors.length)) {
boolean same = false;
for (int i = 0; i < gradientColors.length; i++) {
same = (gradientColors[i] == colors[i]) ||
((gradientColors[i] == null) && (colors[i] == background)) ||
((gradientColors[i] == background) && (colors[i] == null));
if (!same) break;
}
if (same) {
for (int i = 0; i < gradientPercents.length; i++) {
same = gradientPercents[i] == percents[i];
if (!same) break;
}
}
if (same && this.gradientVertical == vertical) return;
}
} else {
backgroundImage = null;
}
// Store the new settings
if (colors == null) {
gradientColors = null;
gradientPercents = null;
gradientVertical = false;
} else {
gradientColors = new Color[colors.length];
for (int i = 0; i < colors.length; ++i)
gradientColors[i] = (colors[i] != null) ? colors[i] : background;
gradientPercents = new int[percents.length];
for (int i = 0; i < percents.length; ++i)
gradientPercents[i] = percents[i];
gradientVertical = vertical;
}
// Refresh with the new settings
redraw();
}
public void setBackground(Image image) {
checkWidget();
if (image == backgroundImage) return;
if (image != null) {
gradientColors = null;
gradientPercents = null;
}
backgroundImage = image;
redraw();
}
public void setBottomMargin(int bottomMargin) {
checkWidget();
if (this.bottomMargin == bottomMargin || bottomMargin < 0) return;
this.bottomMargin = bottomMargin;
redraw();
}
public void setFont(Font font) {
super.setFont(font);
redraw();
}
public void setImage(Image image) {
checkWidget();
if(thread != null) {
thread.stopRunning();
try {
thread.join();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
if (image != this.image) {
this.image = image;
redraw();
}
}
public void setGifImage(String path) {
try {
this.setGifImage(new FileInputStream(new File(path)));
} catch (FileNotFoundException e) {
this.image = null;
return;
}
}
public void setGifImage(InputStream inputStream) {
checkWidget();
if(thread != null) thread.stopRunning();
ImageLoader loader = new ImageLoader();
try {
loader.load(inputStream);
} catch (Exception e) {
this.image = null;
return;
}
if (loader.data[0] != null)
this.image = new Image(this.getDisplay(), loader.data[0]);
if (loader.data.length > 1) {
thread = new GifThread(loader);
thread.start();
}
redraw();
}
#Override
public void dispose() {
super.dispose();
if(thread != null) thread.stopRunning();
}
private class GifThread extends Thread {
private int imageNumber = 0;
private ImageLoader loader = null;
private boolean run = true;
public GifThread(ImageLoader loader) {
this.loader = loader;
}
public void run() {
while(run) {
int delayTime = loader.data[imageNumber].delayTime;
try {
Thread.sleep(delayTime * 10);
} catch (InterruptedException e) {
e.printStackTrace();
}
if(!GifCLabel.this.isDisposed()) {
GifCLabel.this.getDisplay().asyncExec(new Runnable() {
public void run() {
if(!run){
return;
}
if(!GifCLabel.this.isDisposed()) {
imageNumber = imageNumber == loader.data.length - 1 ? 0 : imageNumber + 1;
if (!GifCLabel.this.image.isDisposed()) GifCLabel.this.image.dispose();
ImageData nextFrameData = loader.data[imageNumber];
GifCLabel.this.image = new Image(GifCLabel.this.getDisplay(), nextFrameData);
GifCLabel.this.redraw();
} else stopRunning();
}
});
} else stopRunning();
}
}
public void stopRunning() {
run = false;
}
}
public void setLeftMargin(int leftMargin) {
checkWidget();
if (this.leftMargin == leftMargin || leftMargin < 0) return;
this.leftMargin = leftMargin;
redraw();
}
public void setMargins (int leftMargin, int topMargin, int rightMargin, int bottomMargin) {
checkWidget();
this.leftMargin = Math.max(0, leftMargin);
this.topMargin = Math.max(0, topMargin);
this.rightMargin = Math.max(0, rightMargin);
this.bottomMargin = Math.max(0, bottomMargin);
redraw();
}
public void setRightMargin(int rightMargin) {
checkWidget();
if (this.rightMargin == rightMargin || rightMargin < 0) return;
this.rightMargin = rightMargin;
redraw();
}
public void setText(String text) {
checkWidget();
if (text == null) text = ""; //$NON-NLS-1$
if (! text.equals(this.text)) {
this.text = text;
redraw();
}
}
public void setToolTipText (String string) {
super.setToolTipText (string);
appToolTipText = super.getToolTipText();
}
public void setTopMargin(int topMargin) {
checkWidget();
if (this.topMargin == topMargin || topMargin < 0) return;
this.topMargin = topMargin;
redraw();
}
protected String shortenText(GC gc, String t, int width) {
if (t == null) return null;
int w = gc.textExtent(ELLIPSIS, DRAW_FLAGS).x;
if (width<=w) return t;
int l = t.length();
int max = l/2;
int min = 0;
int mid = (max+min)/2 - 1;
if (mid <= 0) return t;
TextLayout layout = new TextLayout (getDisplay());
layout.setText(t);
mid = validateOffset(layout, mid);
while (min < mid && mid < max) {
String s1 = t.substring(0, mid);
String s2 = t.substring(validateOffset(layout, l-mid), l);
int l1 = gc.textExtent(s1, DRAW_FLAGS).x;
int l2 = gc.textExtent(s2, DRAW_FLAGS).x;
if (l1+w+l2 > width) {
max = mid;
mid = validateOffset(layout, (max+min)/2);
} else if (l1+w+l2 < width) {
min = mid;
mid = validateOffset(layout, (max+min)/2);
} else {
min = max;
}
}
String result = mid == 0 ? t : t.substring(0, mid) + ELLIPSIS + t.substring(validateOffset(layout, l-mid), l);
layout.dispose();
return result;
}
int validateOffset(TextLayout layout, int offset) {
int nextOffset = layout.getNextOffset(offset, SWT.MOVEMENT_CLUSTER);
if (nextOffset != offset) return layout.getPreviousOffset(nextOffset, SWT.MOVEMENT_CLUSTER);
return offset;
}
private String[] splitString(String text) {
String[] lines = new String[1];
int start = 0, pos;
do {
pos = text.indexOf('\n', start);
if (pos == -1) {
lines[lines.length - 1] = text.substring(start);
} else {
boolean crlf = (pos > 0) && (text.charAt(pos - 1) == '\r');
lines[lines.length - 1] = text.substring(start, pos - (crlf ? 1 : 0));
start = pos + 1;
String[] newLines = new String[lines.length+1];
System.arraycopy(lines, 0, newLines, 0, lines.length);
lines = newLines;
}
} while (pos != -1);
return lines;
}
}
and the possible usage is
final GifCLabel lbl = new GifCLabel(shell, SWT.CENTER);
lbl.setText("texxxxt");
lbl.setGifImage(this.getClass().getResourceAsStream("/8EWoM.gif"));
// lbl.setGifImage("src/8EWoM.gif");
Because of the limit of 30000 chars to answer, the pasted code is without comments, non-trim version could be found on http://pastebin.com/cJA682XD