Unity is not showing public methods in the event field 2022 - unity3d

I have 2 mostly identical public methods in the script, but only first one can be shown in the inspector, what happened?
public void playDeadAnim() {
Rigidbody[] allRB = GetComponentsInChildren<Rigidbody>();
for (int r=0;r<allRB.Length;r++) {
allRB[r].isKinematic = false;
}
myAnimator.enabled = false;
}
public void respawnEnemy() {
Rigidbody[] allRB = GetComponentsInChildren<Rigidbody>();
for (int r=0;r<allRB.Length;r++) {
allRB[r].isKinematic = true;
}
myAnimator.enabled = true;
}

Related

MVVM AsyncExecute causing lag

AsyncExecute method causing lag in my treeview application when I am expanding a branch.
Important parts of my TreeView
public DirectoryItemViewModel(string fullPath, DirectoryItemType type, long size)
{
this.ExpandCommand = new AsyncCommand(Expand, CanExecute);
this.FullPath = fullPath;
this.Type = type;
this.Size = size;
this.ClearChildren();
}
public bool CanExecute()
{
return !isBusy;
}
public IAsyncCommand ExpandCommand { get; set; }
private async Task Expand()
{
isBusy = true;
if (this.Type == DirectoryItemType.File)
{
return;
}
List<Task<long>> tasks = new();
var children = DirectoryStructure.GetDirectoryContents(this.FullPath);
this.Children = new ObservableCollection<DirectoryItemViewModel>(
children.Select(content => new DirectoryItemViewModel(content.FullPath, content.Type, 0)));
//If I delete the remaining part of code in this method everything works fine,
in my idea it should output the folders without lag, and then start calculating their size in other threads, but it first lags for 1-2 sec, then output the content of the folder, and then start calculating.
foreach (var item in children)
{
if (item.Type == DirectoryItemType.Folder)
{
tasks.Add(Task.Run(() => GetDirectorySize(new DirectoryInfo(item.FullPath))));
}
}
var results = await Task.WhenAll(tasks);
for (int i = 0; i < results.Length; i++)
{
Children[i].Size = results[i];
}
isBusy = false;
}
My command Interface and class
public interface IAsyncCommand : ICommand
{
Task ExecuteAsync();
bool CanExecute();
}
public class AsyncCommand : IAsyncCommand
{
public event EventHandler CanExecuteChanged;
private bool _isExecuting;
private readonly Func<Task> _execute;
private readonly Func<bool> _canExecute;
public AsyncCommand(
Func<Task> execute,
Func<bool> canExecute = null)
{
_execute = execute;
_canExecute = canExecute;
}
public bool CanExecute()
{
return !_isExecuting && (_canExecute?.Invoke() ?? true);
}
public async Task ExecuteAsync()
{
if (CanExecute())
{
try
{
_isExecuting = true;
await _execute();
}
finally
{
_isExecuting = false;
}
}
RaiseCanExecuteChanged();
}
public void RaiseCanExecuteChanged()
{
CanExecuteChanged?.Invoke(this, EventArgs.Empty);
}
bool ICommand.CanExecute(object parameter)
{
return CanExecute();
}
void ICommand.Execute(object parameter)
{
//I suppose that here is the problem cause IDE is hinting me that I am not awaiting here, but I don't know how to change it if it is.
ExecuteAsync();
}
}

Using admob rewarded ad in unity singleton pattern

I am using admob ads in my app and they are working fine. But when i try to do something after a ad close or reward earned call back my code breaks. Following is my adMob script
public class AdMobScript : MonoBehaviour
{
...
public event Action OnReviveRewardEarned;
public event Action OnReviveAdLoaded;
public event Action OnReviveAdClosed;
private void LoadReviveRewardedAd()
{
reviveRewardedAd = new RewardedAd(adReviveRewardedId);
reviveRewardedAd.OnAdLoaded += ReviveAdLoaded;
reviveRewardedAd.OnUserEarnedReward += ReviveEarnedReward;
reviveRewardedAd.OnAdClosed += ReviveAdClosed;
AdRequest request = new AdRequest.Builder().Build();
reviveRewardedAd.LoadAd(request);
}
private void ReviveAdClosed(object sender, EventArgs e)
{
LoadReviveRewardedAd();
if (isRewardErned)
{
isRewardErned = false;
OnReviveRewardEarned.Invoke();
}
else
OnReviveAdClosed.Invoke();
}
private void ReviveEarnedReward(object sender, Reward e)
{
isRewardErned = true;
}
private void ReviveAdLoaded(object sender, EventArgs e)
{
//reviveButton.interactable = true;
OnReviveAdLoaded.Invoke();
}
public void ShowAdToRevive()
{
if (reviveRewardedAd.IsLoaded())
{
reviveRewardedAd.Show();
}
}
...
}
In the callbacks i am calling my adManager script which is in term using adMob script. Here is the code for it.
public class AdManager : MonoBehaviour
{
...
private void Start() {
AdMobScript.instance.OnReviveAdClosed += ReviveAdClosed;
AdMobScript.instance.OnReviveAdLoaded += ReviveAdLoaded;
AdMobScript.instance.OnReviveRewardEarned += ReviveReward;
}
#region ReviveAds
private void ReviveReward() {
//game crash here
backButton.gameObject.SetActive(true);
reviveButton.gameObject.SetActive(false);
noThanksButton.gameObject.SetActive(false);
manager.Revive();
}
private void ReviveAdLoaded() {
reviveButton.interactable = true;
}
private void ReviveAdClosed() {
//game crash here
reviveButton.interactable = false;
}
public void ShowAdToRevive() {
AdMobScript.instance.ShowAdToRevive();
}
...
}
After either ad close or reward earned my game crashes (error log says
get_gameObject can only be called from the main thread
). There must be something i am doing wrong. Can anyone please point me to the right direction?
The reason for the problem - you trying to manipulate with MonoBehaviors, not in main thread.
Just write simple scheduler which calls the events in the Unity thread, like this:
Scheduler:
using System;
using UnityEngine;
public class Scheduler : MonoBehaviour
{
public static Scheduler instance;
public event Action secondTick = delegate { };
private float seconds = 0;
private void Awake()
{
instance = this;
}
private void Update()
{
seconds += Time.unscaledDeltaTime;
if (seconds >= 1.0f)
{
seconds -= 1.0f;
secondTick.Invoke();
}
}
}
Updated AdMobScript:
public class AdMobScript : MonoBehaviour
{
...
private bool onRewardEarnedCall = false;
private bool onRewardAdLoaded = false;
private bool onRewardAdClosed = false;
public event Action OnReviveRewardEarned;
public event Action OnReviveAdLoaded;
public event Action OnReviveAdClosed;
private void LoadReviveRewardedAd()
{
reviveRewardedAd = new RewardedAd(adReviveRewardedId);
reviveRewardedAd.OnAdLoaded += ReviveAdLoaded;
reviveRewardedAd.OnUserEarnedReward += ReviveEarnedReward;
reviveRewardedAd.OnAdClosed += ReviveAdClosed;
AdRequest request = new AdRequest.Builder().Build();
reviveRewardedAd.LoadAd(request);
Scheduler.instance.secondTick += OnSecondTick;
}
private void OnSecondTick()
{
if(onRewardAdClosed)
{
onRewardAdClosed = false;
OnReviveAdClosed.Invoke();
}
if(onRewardEarnedCall)
{
OnReviveRewardEarned.Invoke();
onRewardEarnedCall = false;
}
if(onRewardAdLoaded)
{
OnReviveAdLoaded.Invoke();
onRewardAdLoaded = false;
}
}
private void ReviveAdClosed(object sender, EventArgs e)
{
LoadReviveRewardedAd();
if (isRewardErned)
{
isRewardErned = false;
onRewardEarnedCall = true;
}
else
onRewardAdClosed = true;
}
private void ReviveEarnedReward(object sender, Reward e)
{
isRewardErned = true;
}
private void ReviveAdLoaded(object sender, EventArgs e)
{
//reviveButton.interactable = true;
onRewardAdLoaded = true;
}
public void ShowAdToRevive()
{
if (reviveRewardedAd.IsLoaded())
{
reviveRewardedAd.Show();
}
}
...
}
This is a very simple and not optimize solution but this will solve your problem.

Unity: Google Play Games crashes on login

I'm trying to save a variable using google play games cloud save. However it crashes when it signs in. I've definitely enabled it on the developer console. I never had this problem before I added the cloud save feature and it was just doing achievements and scoreboards. Also, when I'm not connected to the internet, it doesn't crash and locally saving the data works fine. Can any one help?
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using GooglePlayGames;
using GooglePlayGames.BasicApi;
using GooglePlayGames.BasicApi.SavedGame;
using System.Text;
public class playgamesscript : MonoBehaviour {
public static playgamesscript Instance { get; private set; }
const string SAVE_NAME = "Test";
bool isSaving;
textEdit textEditScript;
control controlScript;
bool isCloudDataLoaded;
// Use this for initialization
void Start () {
Instance = this;
textEditScript = GameObject.FindGameObjectWithTag("UIControl").GetComponent<textEdit>();
controlScript = GameObject.FindGameObjectWithTag("Control").GetComponent<control>();
if (!PlayerPrefs.HasKey(SAVE_NAME))
PlayerPrefs.SetString(SAVE_NAME, "0");
if (!PlayerPrefs.HasKey("IsFirstTime"))
PlayerPrefs.SetInt("IsFirstTime", 1);
LoadLocal();
PlayGamesClientConfiguration config = new PlayGamesClientConfiguration.Builder().EnableSavedGames().Build();
PlayGamesPlatform.InitializeInstance(config);
PlayGamesPlatform.Activate();
if (control.signInAttempt == false)
{
SignIn();
}
}
void SignIn()
{
control.signInAttempt = true;
Social.localUser.Authenticate(success => { LoadData(); });
}
#region Saved Games
string GameDataToString()
{
return control.Highscore.ToString();
}
void StringToGameData(string cloudData, string localData)
{
if (PlayerPrefs.GetInt("IsFirstTime") == 1){
PlayerPrefs.SetInt("IsFirstTime", 0);
if (int.Parse(cloudData) > int.Parse(localData)){
PlayerPrefs.SetString(SAVE_NAME, cloudData);
}
}
else if (int.Parse(localData) > int.Parse(cloudData))
{
control.Highscore = int.Parse(localData);
AddScoreToLoeaderBoard(textEdit.leaderboardStat, control.Highscore);
isCloudDataLoaded = true;
SaveData();
return;
}
control.Highscore = int.Parse(cloudData);
isCloudDataLoaded = true;
}
void StringToGameData (string localData)
{
control.Highscore = int.Parse(localData);
}
void LoadData()
{
if (Social.localUser.authenticated)
{
isSaving = false;
((PlayGamesPlatform)Social.Active).SavedGame.OpenWithManualConflictResolution(SAVE_NAME, DataSource.ReadCacheOrNetwork, true, ResolveConflict, OnSavedGameOpened);
}
else {
LoadLocal();
}
}
private void LoadLocal()
{
StringToGameData(PlayerPrefs.GetString(SAVE_NAME));
}
public void SaveData()
{
if (!isCloudDataLoaded)
{
SaveLocal();
return;
}
if (Social.localUser.authenticated)
{
isSaving = true;
((PlayGamesPlatform)Social.Active).SavedGame.OpenWithManualConflictResolution(SAVE_NAME, DataSource.ReadCacheOrNetwork, true, ResolveConflict, OnSavedGameOpened);
}
else
{
SaveLocal();
}
}
private void SaveLocal()
{
PlayerPrefs.SetString(SAVE_NAME, GameDataToString());
}
private void ResolveConflict(IConflictResolver resolver, ISavedGameMetadata original, byte[] originalData, ISavedGameMetadata unmerged, byte[] unmergedData)
{
if (originalData == null)
{
resolver.ChooseMetadata(unmerged);
} else if (unmergedData == null)
{
resolver.ChooseMetadata(original);
} else
{
string originalStr = Encoding.ASCII.GetString(originalData);
string unmergedStr = Encoding.ASCII.GetString(unmergedData);
int originalNum = int.Parse(originalStr);
int unmergedNum = int.Parse(unmergedStr);
if (originalNum > unmergedNum)
{
resolver.ChooseMetadata(original);
return;
} else if (unmergedNum> originalNum)
{
resolver.ChooseMetadata(unmerged);
}
resolver.ChooseMetadata(original);
}
}
private void OnSavedGameOpened(SavedGameRequestStatus status, ISavedGameMetadata game)
{
if (status == SavedGameRequestStatus.Success)
{
if (!isSaving)
{
LoadGame(game);
} else
{
SaveGame(game);
}
}
else
{
if (!isSaving)
{
LoadLocal();
}else
{
SaveLocal();
}
}
}
private void LoadGame(ISavedGameMetadata game)
{
((PlayGamesPlatform)Social.Active).SavedGame.ReadBinaryData(game, OnSavedGameDataRead);
}
private void SaveGame(ISavedGameMetadata game)
{
string stringToSave = GameDataToString();
PlayerPrefs.SetString(SAVE_NAME, stringToSave);
byte[] dataToSave = Encoding.ASCII.GetBytes(stringToSave);
SavedGameMetadataUpdate update = new SavedGameMetadataUpdate.Builder().Build();
((PlayGamesPlatform)Social.Active).SavedGame.CommitUpdate(game, update, dataToSave, OnSavedGameDataWritten);
}
private void OnSavedGameDataRead(SavedGameRequestStatus status, byte[] savedData)
{
if (status == SavedGameRequestStatus.Success)
{
string cloudDataString;
if (savedData.Length == 0)
{
cloudDataString = "0";
} else
cloudDataString = Encoding.ASCII.GetString(savedData);
string localDataString = PlayerPrefs.GetString(SAVE_NAME);
StringToGameData(cloudDataString, localDataString);
}
}
private void OnSavedGameDataWritten(SavedGameRequestStatus status, ISavedGameMetadata game)
{
}
#endregion /Saved Games
///
JNI DETECTED ERROR IN APPLICATION: can't call void com.google.android.gms.common.api.PendingResult.setResultCallback(com.google.android.gms.common.api.ResultCallback) on null object'

Cannot access array of a custom class

In unity I keep getting the error message "NullReferenceException: Object reference not set to an instance of an object" on this:
listOfBanks[0].Deposit(50);
and
accntBlnce.text = "Account Balance:\n" + listOfBanks[curBank].GetBalance().ToString("c");
I have 3 options listed in the drop down menu and when I Debug.Log the number of items in the array I get 3 as my count. But I can't do anything with them. The banks variable is set as the Dropdown object in the inspector as well as the accntBlnce as the text object in my panel.
The code is below.
Banks.cs
public class Banks : MonoBehaviour {
public Dropdown banks;
public Text accntBlnce;
public Bank[] listOfBanks;
public int curBank = 0;
void Start() {
listOfBanks = new Bank[banks.options.Count];
listOfBanks[0].Deposit(50);
}
void Update() {
curBank = banks.value;
accntBlnce.text = "Account Balance:\n" + listOfBanks[curBank].GetBalance().ToString("c");
}
}
Bank.cs
public class Bank{
public Bank() { }
public Bank(string orgn, float amntToRprt, float blnce) {
origin = orgn;
amountToReport = amntToRprt;
balance = blnce;
}
public string origin { get; set; }
public float amountToReport { get; set; }
public float balance { get; set; }
public bool Deposit(float amnt) {
if (amnt > 0) {
balance += amnt;
if(amnt > amountToReport) {
FlagForReport();
}
return true;
}
else
return false;
}
private void FlagForReport() {
throw new NotImplementedException();
}
public float GetBalance() {
return balance;
}
public bool Withdraw(float amnt) {
if (amnt > 0) {
if (balance >= amnt) {
balance -= amnt;
return true;
}
else
return false;
}
else
return false;
}
public bool Transfer(float amnt, Bank bank) {
if (amnt > 0) {
if (balance >= amnt) {
if(bank.Deposit(amnt))
balance -= amnt;
return true;
}
else
return false;
}
else
return false;
}
}
This is the fourth time array question is asked this week with the-same problem and the-same solution.
You declared the array here:
listOfBanks = new Bank[banks.options.Count];
but you did not create new instance of each Bank script before calling
listOfBanks[0].Deposit(50); and listOfBanks[curBank].GetBalance().ToString("c").
Declaring array and setting the size is NOT the-same as creating new instance of a script.
The solution is to loop through the array and create new instance of each one.
In your Banks.cs, replace the code in your Start() function with the one below:
void Start()
{
//Declare how much Bank array should be created
listOfBanks = new Bank[banks.options.Count];
//Now Create instance of each bank
for (int i = 0; i < listOfBanks.Length; i++)
{
//Create new instance of each Bank class
//listOfBanks[i] = new Bank();
listOfBanks[i] = new Bank("", 50, 50);
}
listOfBanks[0].Deposit(50);
}

Making a drag and drop FlexTable in GWT 2.5

I'm trying to make a simple Drag and Drop FlexTable using native GWT drag events to allow the user to move rows around.
//This works fine
galleryList.getElement().setDraggable(Element.DRAGGABLE_TRUE);
galleryList.addDragStartHandler(new DragStartHandler() {
#Override
public void onDragStart(DragStartEvent event) {
event.setData("text", "Hello World");
groupList.getElement().getStyle().setBackgroundColor("#aff");
}
});
However, I'd like to:
1. Give a visual indicator where the item will be dropped.
2. Work out where i should drop the row, when the drop event fires.
galleryList.addDragOverHandler(new DragOverHandler() {
#Override
public void onDragOver(DragOverEvent event) {
//TODO: How do i get the current location one would drop an item into a flextable here
}
});
galleryList.addDragEndHandler(new DragEndHandler() {
#Override
public void onDragEnd(DragEndEvent event) {
//TODO: How do i know where i am in the flextable
}
});
I see these FlexTable methods are useful in getting a cell/row:
public Cell getCellForEvent(ClickEvent event)
protected Element getEventTargetCell(Event event)
But the problem is the Drag events do not inherit of Event
Thanks in advance
Caveat: I cant gaurentee this will work out the box. This is the code I ended up making (And works for me) - it's a Drag n Drop Widget which inherits from FlexTable. I detect any drag events on the table, and then try compute where the mouse is over that FlexTable.
import com.google.gwt.dom.client.TableRowElement;
import com.google.gwt.event.dom.client.*;
import com.google.gwt.user.client.DOM;
import com.google.gwt.user.client.Element;
import com.google.gwt.user.client.Event;
import com.google.gwt.user.client.ui.FlexTable;
import com.google.gwt.user.client.ui.Widget;
public class DragFlexTable extends FlexTable implements DraggableWidget {
public String dragStyle = "drag-table-row";
public String dragReplaceStyle;
protected DragVerticalHandler dragFlexTableHandler;
private int currentRow;
private int[] yLocations;
private int rowBeingDragged;
DragFlexTable() {
sinkEvents(Event.ONMOUSEOVER | Event.ONMOUSEOUT);
getElement().setDraggable(Element.DRAGGABLE_TRUE);
final DragUtil dragUtil = new DragUtil();
addDragStartHandler(new DragStartHandler() {
#Override
public void onDragStart(DragStartEvent event) {
dragUtil.startVerticalDrag(event, DragFlexTable.this);
}
});
addDragEndHandler(new DragEndHandler() {
#Override
public void onDragEnd(DragEndEvent event) {
dragUtil.endVerticalDrag(event, DragFlexTable.this);
}
});
addDragOverHandler(new DragOverHandler() {
#Override
public void onDragOver(DragOverEvent event) {
dragUtil.handleVerticalDragOver(event, DragFlexTable.this, 3);
}
});
}
#Override
public void onBrowserEvent(Event event) {
super.onBrowserEvent(event);
Element td = getEventTargetCell(event);
if (td == null) return;
Element tr = DOM.getParent(td);
currentRow = TableRowElement.as(td.getParentElement()).getSectionRowIndex();
switch (DOM.eventGetType(event)) {
case Event.ONMOUSEOVER: {
//tr.addClassName(ROW_STYLE_NAME + "-mouseover");
tr.addClassName(dragStyle);
break;
}
case Event.ONMOUSEOUT: {
tr.removeClassName(dragStyle);
break;
}
}
}
public void setDragStyle(String dragStyle) {
this.dragStyle = dragStyle;
}
#Override
public void resetDragState() {
yLocations = null;
}
#Override
public void setRowBeingDragged(int currentRow) {
this.rowBeingDragged = currentRow;
}
#Override
public int getDragRow(DragDropEventBase event) {
if (yLocations == null) {
yLocations = new int[getRowCount()];
for (int i = 0; i < getRowCount(); i++) {
Widget widget = getWidget(i, 0);
if (widget.isVisible()) {
com.google.gwt.dom.client.Element imgTd = widget.getElement().getParentElement();
int absoluteBottom = imgTd.getAbsoluteBottom();
yLocations[i] = absoluteBottom;
} else {
yLocations[i] = -1;
}
}
}
int lastY = 0;
for (int i = 0; i < yLocations.length; i++) {
int absoluteBottom = yLocations[i];
//invisible
if (absoluteBottom != -1) {
int absoluteTop = lastY;
int clientY = event.getNativeEvent().getClientY();
if (absoluteBottom > clientY && absoluteTop < clientY) {
//com.google.gwt.dom.client.Element tr = imgTd.getParentElement();
return i;
}
lastY = absoluteBottom;
}
}
return currentRow;
}
#Override
public com.google.gwt.dom.client.Element getTrElement(int row) {
return getWidget(row, 0).getElement().getParentElement().getParentElement();
}
#Override
public DragVerticalHandler getDragFlexTableHandler() {
return dragFlexTableHandler;
}
public void setDragReplaceStyle(String dragReplaceStyle) {
this.dragReplaceStyle = dragReplaceStyle;
}
#Override
public int getRowBeingDragged() {
return rowBeingDragged;
}
#Override
public String getDragReplaceStyle() {
return dragReplaceStyle;
}
public void setDragFlexTableHandler(DragVerticalHandler dragFlexTableHandler) {
this.dragFlexTableHandler = dragFlexTableHandler;
}
}
This is util class which it uses
import com.google.gwt.event.dom.client.DragEndEvent;
import com.google.gwt.event.dom.client.DragOverEvent;
import com.google.gwt.event.dom.client.DragStartEvent;
import com.google.gwt.user.client.ui.Image;
public class DragUtil {
private int alternateIgnoreEvent = 0;
private int lastDragRow = -1;
public void startVerticalDrag(DragStartEvent event, DraggableWidget widget) {
widget.resetDragState();
//Required
event.setData("text", "dragging");
int currentRow = widget.getDragRow(event);
widget.setRowBeingDragged(currentRow);
if (widget.getDragFlexTableHandler()!=null) {
Image thumbnailImg = widget.getDragFlexTableHandler().getImage(currentRow);
if (thumbnailImg!=null) {
event.getDataTransfer().setDragImage(thumbnailImg.getElement(), -10, -10);
}
}
}
public void handleVerticalDragOver(DragOverEvent event, DraggableWidget widgets, int sensitivity) {
if (alternateIgnoreEvent++ % sensitivity != 0) {
//many events fire, for every pixel move, which slow the browser, so ill ignore some
return;
}
int dragRow = widgets.getDragRow(event);
if (dragRow != lastDragRow) {
com.google.gwt.dom.client.Element dragOverTr = widgets.getTrElement(dragRow);
if (lastDragRow != -1) {
com.google.gwt.dom.client.Element lastTr = widgets.getTrElement(lastDragRow);
lastTr.removeClassName(widgets.getDragReplaceStyle());
}
lastDragRow = dragRow;
dragOverTr.addClassName(widgets.getDragReplaceStyle());
}
}
public void endVerticalDrag(DragEndEvent event, DraggableWidget widgets) {
int newRowPosition = widgets.getDragRow(event);
//cleanup last position
if (newRowPosition != lastDragRow) {
com.google.gwt.dom.client.Element lastTr = widgets.getTrElement(lastDragRow);
lastTr.removeClassName(widgets.getDragReplaceStyle());
}
if (newRowPosition != widgets.getRowBeingDragged()) {
com.google.gwt.dom.client.Element dragOverTr = widgets.getTrElement(newRowPosition);
dragOverTr.removeClassName(widgets.getDragReplaceStyle());
widgets.getDragFlexTableHandler().moveRow(widgets.getRowBeingDragged(), newRowPosition);
}
}
}
In the uibinder I then use it like this:
<adminDnd:DragFlexTable ui:field='itemFlexTable' styleName='{style.table}' cellSpacing='0'
cellPadding='0'
dragStyle='{style.drag-table-row-mouseover}'
dragReplaceStyle='{style.drag-replace-table-row}'
/>
Even i had this problem and after a little prototyping this is what I ended up with
.I created a class which extended the flex table.Here is the code
public class DragFlexTable extends FlexTable implements
MouseDownHandler,MouseUpHandler,MouseMoveHandler,
MouseOutHandler
{
private int row,column,draggedrow,draggedcolumn;
private Element td;
private Widget w;
private boolean emptycellclicked;
DragFlexTable()
{
sinkEvents(Event.ONMOUSEOVER | Event.ONMOUSEOUT | Event.ONMOUSEDOWN | Event.ONMOUSEMOVE);
this.addMouseDownHandler(this);
this.addMouseMoveHandler(this);
this.addMouseUpHandler(this);
this.addMouseOutHandler(this);
}
#Override
public void onBrowserEvent(Event event)
{
super.onBrowserEvent(event);
td = getEventTargetCell(event);
if (td == null)
{
return;
}
Element tr = DOM.getParent((com.google.gwt.user.client.Element) td);
Element body = DOM.getParent((com.google.gwt.user.client.Element) tr);
row = DOM.getChildIndex((com.google.gwt.user.client.Element) body, (com.google.gwt.user.client.Element) tr);//(body, tr);
column = DOM.getChildIndex((com.google.gwt.user.client.Element) tr, (com.google.gwt.user.client.Element) td);
}
boolean mousedown;
#Override
public void onMouseDown(MouseDownEvent event)
{
if (event.getNativeButton() == NativeEvent.BUTTON_LEFT)
{
//to ensure empty cell is not clciked
if (!td.hasChildNodes())
{
emptycellclicked = true;
}
event.preventDefault();
start(event);
mousedown = true;
}
}
#Override
public void onMouseMove(MouseMoveEvent event)
{
if (mousedown)
{
drag(event);
}
}
#Override
public void onMouseUp(MouseUpEvent event)
{
if (event.getNativeButton() == NativeEvent.BUTTON_LEFT)
{
if (!emptycellclicked)
{
end(event);
}
emptycellclicked = false;
mousedown = false;
}
}
#Override
public void onMouseOut(MouseOutEvent event)
{
this.getCellFormatter().getElement(row, column).getStyle().clearBorderStyle();
this.getCellFormatter().getElement(row, column).getStyle().clearBorderColor();
this.getCellFormatter().getElement(row, column).getStyle().clearBorderWidth();
w.getElement().getStyle().setOpacity(1);
mousedown = false;
}
private void start(MouseDownEvent event)
{
w = this.getWidget(row, column);
w.getElement().getStyle().setOpacity(0.5);
}
private void drag(MouseMoveEvent event)
{
if (draggedrow != row || draggedcolumn != column)
{
this.getCellFormatter().getElement(draggedrow, draggedcolumn).getStyle().clearBorderStyle();
this.getCellFormatter().getElement(draggedrow, draggedcolumn).getStyle().clearBorderColor();
this.getCellFormatter().getElement(draggedrow, draggedcolumn).getStyle().clearBorderWidth();
this.draggedrow = row;
this.draggedcolumn = column;
this.getCellFormatter().getElement(row, column).getStyle().setBorderStyle(BorderStyle.DASHED);
this.getCellFormatter().getElement(row, column).getStyle().setBorderColor("black");
this.getCellFormatter().getElement(row, column).getStyle().setBorderWidth(2, Unit.PX);
}
}
private void end(MouseUpEvent event)
{
insertDraggedWidget(row, column);
}
private void insertDraggedWidget(int r,int c)
{
this.getCellFormatter().getElement(r, c).getStyle().clearBorderStyle();
this.getCellFormatter().getElement(r, c).getStyle().clearBorderColor();
this.getCellFormatter().getElement(r, c).getStyle().clearBorderWidth();
w.getElement().getStyle().setOpacity(1);
if (this.getWidget(r, c) != null)
{
//pushing down the widgets already in the column
// int widgetheight = (this.getWidget(r, c).getOffsetHeight() / 2) + this.getWidget(r, c).getAbsoluteTop();
// int rw;
//placing the widget above the dropped widget
for (int i = this.getRowCount() - 1; i >= r; i--)
{
if (this.isCellPresent(i, c))
{
this.setWidget(i + 1, c, this.getWidget(i, c));
}
}
}
this.setWidget(r, c, w);
//removes unneccesary blank rows
cleanupRows();
//pushing up the column in the stack
// for (int i = oldrow;i<this.getRowCount()-1 ;i++)
// {
//
// this.setWidget(i ,oldcolumn, this.getWidget(i+1, oldcolumn));
//
// }
}
private void cleanupRows()
{
ArrayList<Integer> rowsfilled = new ArrayList<Integer>();
for (int i = 0; i <= this.getRowCount() - 1; i++)
{
for (int j = 0; j <= this.getCellCount(i) - 1; j++)
{
if (this.getWidget(i, j) != null)
{
rowsfilled.add(i);
break;
}
}
}
//replace the empty rows
for (int i = 0; i < rowsfilled.size(); i++)
{
int currentFilledRow = rowsfilled.get(i);
if (i != currentFilledRow)
{
for (int j = 0; j < this.getCellCount(currentFilledRow); j++)
{
this.setWidget(i, j, this.getWidget(currentFilledRow, j));
}
}
}
for (int i = rowsfilled.size(); i < this.getRowCount(); i++)
{
this.removeRow(i);
}
}
public HandlerRegistration addMouseUpHandler(MouseUpHandler handler)
{
return addDomHandler(handler, MouseUpEvent.getType());
}
public HandlerRegistration addMouseDownHandler(MouseDownHandler handler)
{
return addDomHandler(handler, MouseDownEvent.getType());
}
public HandlerRegistration addMouseMoveHandler(MouseMoveHandler handler)
{
return addDomHandler(handler, MouseMoveEvent.getType());
}
public HandlerRegistration addMouseOutHandler(MouseOutHandler handler)
{
return addDomHandler(handler, MouseOutEvent.getType());
}
}
and the on module load for the above custom widget is
public void onModuleLoad()
{
Label a = new Label("asad");
Label b = new Label("ad");
Label c = new Label("qwad");
Label w = new Label("zxd");
a.setPixelSize(200, 200);
a.getElement().getStyle().setBorderStyle(BorderStyle.SOLID);
a.getElement().getStyle().setBorderWidth(1, Unit.PX);
b.setPixelSize(200, 200);
c.setPixelSize(200, 200);
w.setPixelSize(200, 200);
a.getElement().getStyle().setBackgroundColor("red");
b.getElement().getStyle().setBackgroundColor("yellowgreen");
c.getElement().getStyle().setBackgroundColor("lightblue");
w.getElement().getStyle().setBackgroundColor("grey");
DragFlexTable d = new DragFlexTable();
d.setWidget(0, 0, a);
d.setWidget(0, 1, b);
d.setWidget(1, 0, c);
d.setWidget(1, 1, w);
d.setCellPadding(20);
RootPanel.get().add(d);
}