Cocos2dx CCTableView issue - cocos2d-x

I have made a drop down list using CCTableView. Its working quite ok. Now i have to hide the table when i select any entry. So i have written following code.
void Sample1::tableCellTouched(CCTableView* table, CCTableViewCell* cell)
{
CCLOG("cell touched at index: %i", cell->getIdx());
table->setVisible(false);
}
When this is executed the table becomes invisible, but when i try to again make it visible it(CCTableView) doesn't respond to any touches, while the other buttons are responding.
Can anyone guess what might be going wrong!?

It's because CCTableView itself checks if it's visible and won't process touches if it's invisible.
Here the responsible section in CCTableView.cpp:
if (!this->isVisible()) {
return;
}
This snippet is both in ccTouchBegan and ccTouchEnded.
Your delegate's tableCellTouched will be called inside CCTableView's ccTouchEnded, so you would have to make your table visible in a function that is not dependent on calls from CCTableView.

For adding Tablecell in CCTable
Make a class named CustomClass:
In CustomClass.cpp
CCTableCell* CustomClass::tableMethod(CCTable* pTable, unsigned int idx)
{
CCTableCell* tableCell = pTable->dequeueCell();
if(!tableCell)
{
tableCell = new CCTableCell();
addChild(tableCell);
}
return tableCell;
}

Related

SWT JFACE: How to move one row to another row in JFace TableViewer by using TAB Key [duplicate]

What I'd like to do is be able to tab between elements in table.
I currently am creating my table like this.
this.tableViewer =
new TableViewer(parent , SWT.FULL_SELECTION);
tableViewer.setUseHashlookup(true);
table = tableViewer.getTable();
GridData gridData = new GridData(GridData.FILL_BOTH);
gridData.grabExcessVerticalSpace = true;
table.setLayoutData(gridData);
table.setLinesVisible(true);
table.setHeaderVisible(true);
...
/** Create the Cell Editor Array - will hold all columns **/
editors = new CellEditor[table.getColumnCount()];
/** Cell Editor Row 1 **/
/** Set the column properties **/
tableViewer.setColumnProperties(columnNames);
/** Assign the cell editors to the viewer **/
tableViewer.setCellEditors(editors);
/** Set the cell modifier for the viewer **/
tableViewer.setCellModifier(new MyCellModifier(this));
//Create the Table Viewer
/** Table Viewer Content and Label Provider **/
tableViewer.setContentProvider(new MyContentProvider(this));
tableViewer.setLabelProvider(new MyLabelProvider());
But I'm not sure how to set up the tabulation. Everything else works as far as editing columns, showing data, etc. Just stuck on this last part.
If I've missed obvious documentation or javadocs - my apologies and even pointing to those would be great.
Although the solution thehiatus posted is very low level and will probably work (I haven't tested it), JFace gives you a framework for this specific problem. See the org.eclipse.jface.viewers.TableViewerFocusCellManager along with org.eclipse.jface.viewers.CellNavigationStrategy classes to solve this problem.
I think by default tab does not jump from cell to cell in an swt table. Instead it traverses to the next control. So you'll also need to tell it not to traverse when tab is pressed
KeyListener keyListener = new KeyLisener()
{
public void keyPressed(KeyEvent evt)
{
if (evt.keyCode == SWT.TAB)
{
// There are numerous setSelection methods. I'll leave this to you.
tableViewer.getTable().setSelection(...)
}
}
public void keyReleased(KeyEvent evt){}
}
TraverseListener traverseListener = new TraverseListener()
{
public void keyTraversed(TraverseEvent evt)
{
if (evt.keyCode == SWT.TAB)
evt.doit = false;
}
}
tableViewer.getTable().addKeyListener(keyListener);
tableViewer.getTable().addTraverseListener(traverseListener);
Also, as derBiggi suggested, the listeners need to be added to the Table object, not the TableViewer.
I couldn't get the desired behavior with a TraverseListener (it would not traverse within the table), and I had trouble getting it to work with a FocusCellManager and CellNavigationStrategy. I finally found this solution that enables me to tab from column to column within a row and automatically activate the editor.
Viewer viewer = ...
TableViewerFocusCellManager focusCellManager =
new TableViewerFocusCellManager(
viewer,
new FocusCellHighlighter(viewer) {});
ColumnViewerEditorActivationStrategy editorActivationStrategy =
new ColumnViewerEditorActivationStrategy(viewer) {
#Override
protected boolean isEditorActivationEvent(
ColumnViewerEditorActivationEvent event) {
ViewerCell cell = (ViewerCell) event.getSource();
return cell.getColumnIndex() == 1 || cell.getColumnIndex() == 2;
}
};
TableViewerEditor.create(viewer, focusCellManager, editorActivationStrategy,
TableViewerEditor.TABBING_HORIZONTAL);
You need to add a KeyListener and set the selection or focus to the next cell:
tableViewer.getTable().addKeyListener(new KeyListener(){
public void keyPressed(KeyEvent e) {
System.out.println("Key Pressed");
if (e.keycode == SWT.TAB)
{
System.out.println("Detected TAB key");
// set table viewer selection
}
}
public void keyReleased(KeyEvent e) {
System.out.println("Key Released");
}}
);
I also had to implement tabbing between elements in a table. We use Grid from Nebula as the table.
Firstly, I had to suppress tabbing the focus preventing it from moving out of the table.
and then I added a Key Listener which moves the focus/selection to the next cell:
I also made my own algorithm to move the selection one cell to the right and when at the end of the row, move it to the beginning of the next row. When end of table is reached, the selection moves back to the first cell in the table.
This solved the problem for me.

ActionScript 3 Selecting a MovieClip

My situation is this:
I've got several (2+) MovieClips on the stage.
Each one contains an input-textbox in addition to the background.
When I click the first MovieClip, it gets selected and a light blue shadow is displayed to indicate it like so: http://puu.sh/aueAw/3575e83aca.png
If I click the second one, it looks like this: http://puu.sh/aueEj/826e1c9cb9.png
However, when the second MovieClip's textbox is clicked, the first MovieClip becomes selected! This doesn't make any sense to me.
What could be causing this? Everything works as it should as long as I don't take these nested textboxes into account.
Thanks in advance for your helpful answers!
Best regards,
Olin K.
EDIT: Here's the code that I use to add event listeners to the MovieClips.
public function updateVisualDocument()
{
if (!uniDocument.isEmpty())
{
//Update the Visual Document if the current Document contains any pages
visualDocument.uniPage.gotoAndStop(uniDocument.getCurrentPage().getLayout());
visualDocument.uniPage.pageNumber.text = uniDocument.getPageIndex();
//Update Thumbnails
for each (var someThumb in thumbnailArray)
{
someThumb.deselect();
}
thumbnailArray[uniDocument.getPageIndex() - 1].select();
for (var i:int = 0; i < visualDocument.uniPage.panelContainer.numChildren; i++)
{
var somePanelMC = visualDocument.uniPage.panelContainer.getChildAt(i);
if (!uniDocument.getCurrentPage().hasPanels())
{
uniDocument.getCurrentPage().addPanel(somePanelMC);
}
somePanelMC.addEventListener(MouseEvent.CLICK, panelClicked);
uniDocument.getCurrentPage().getPanel(i).setPanelMC(somePanelMC);
function panelClicked(e:Event)
{
//Panel gets selected
var panelIndex:int = int(e.target.name.substring(5));
uniDocument.getCurrentPage().deselectAllPanels();
uniDocument.getCurrentPage().getPanel(panelIndex).select();
}
}
uniDocument.getCurrentPage().panelsAreFull();
uniDocument.getCurrentPage().selectFirst();
}
}
EDIT: I tried changing the textbox to the dynamic text (from the input text) type and the problem is still exactly the same. I click the textbox, it selects the first MovieClip. I think it may have to do with using the same instance name, but since it's nested, why should it matter?
Looks like I figured it out on my own. Partially. I worked off what LDMS said in his comment "did you accidentally give them the same instance name?"
Well, no, I didn't. BUT- the textboxes all had the same instance name. This is irrelevant, but it got me focused on the textboxes names, and I realized that since I had mouseChildren set to false, the textboxes were the ones firing off the event listener.
So I changed up a bit of my code to look like this:
function panelClicked(e:Event)
{
//Panel gets selected
if (!e.target.name == "myText")
{
var panelIndex:int = int(e.target.name.substring(5));
uniDocument.getCurrentPage().deselectAllPanels();
uniDocument.getCurrentPage().getPanel(panelIndex).select();
}
}
And now it works! It's a simple workaround, since doing myText.mouseEnabled = false; was not an option because it needed to be clicked.
Hope this helps someone in the future! Cheers!

How to remove this unrelated block of code, that checks child's availability in the container

This is my code on button click. It adds myView to the container. And takes care of fact that all previous instances get removed before adding again. I wanna know, if there is some better way of making this "check" ? I especially wanna have some way to remove the 1s 7 lines of this code ( within comments). It seems like an unrelated block of code in the normal code-flow.
function button_CLICK(e:Event)
{
///////////////////////////////////////////////////
if ( myView!= null)
{
if ( contains(myView))
{
removeChild(myView) ;
}
}
/////////////////////////////////////////////////////
myView = new myView("hello")
addChild(myView);
}
it would depend on what the object myView consists of. if, for example, it has its own event listeners you would want to use the condition check to clean up the object before disposing of it so there are no memory leaks.
function button_CLICK(e:Event):void
{
if (myView && contains(myView))
{
//clean up myView
removeChild(myView);
}
myView = new myView("hello");
addChild(myView);
}
however, if myView is a simple display object that doesn't contain any leakable references or event listeners than you could simply reassign the variable to overwrite the previous.
keep in mind that addChild() places the added display object on top above all others. but regardless if that's something you'd like to avoid or not, i believe it would be better to assign a default or empty view once instead of addChild(myView) each time the button is clicked.
function button_CLICK(e:Event):void
{
myView = new myView("hello");
}
i assume your code is for for demonstration because new myView("hello") is going to always be the same object? unless perhaps this object relies on dates or timers to make instances different from previous constructs.
The checking code you have could create a memory leak as you don't null the previous myView before creating a new instance. NB. It's good practice to begin the name of your classes with an uppercase letter.
Your code also seems to allow for the button_CLICK method to be called when myView has been added. Perhaps consider hiding the button when the view has been added.
You could just have one instance of the MyView Class instantiated. Then rather than having to null and create a new instance each time, just add the same one and add an init function that will accept the initialising parameters. e.g.
var myView = new MyView();
function button_CLICK(e:Event)
{
if ( contains(myView))
{
removeChild(myView) ;
}
}
myView.init("hello");
addChild(myView);
}
I don't think you have much of an option, based on the (IMO) flawed implementation of DisplayObjectContainer. If you're feeling feisty, you can "fix" removeChild to see if the child is there before calling the super method, rather than simply throwing an error, as Adobe thought was the appropriate solution.
Your code above will still run, but it will be in the removeChild override.
Your commented bloc of code is necessary only for the first call to button_CLICK (you sould rename this method : buttonClick).
After the firts call, this bloc of code is unnecessary.
In order to remove this code myView should be not null, and an instance of MyView should be added on the display list.
var myView : MyView;
function init(){
myView = new MyView("FAKE");
myView.visible = false;
addChild(myView);
addEventListener("click",click);
}
function click(e:MouseEvent):void{
removeChild(myView);
myView = new Child("REAL");
addChild(myView);
}
Try:
if(myView != null)
myView.parent && myView.parent.removeChild(myView);

checking if child exists

Hello i have a function as following:
private function seatClickHandler(e:MouseEvent):void{
var check:Check = new Check();
if(e.target.contains(check)){
e.target.removeChild(seat);
}else{
e.target.addChild(check);
}
}
basicly i want to check if e.target contains a child called check. If it does i want e.target to remove the child, else i want to add the child. But the method i tried doesnt seem to work although i think this is the way to go. Any suggestions?
When you declare your Check object, Actionscript creates a reference code for that specific object.
So the first time your code is run, your Check object could be given a reference of #c0ecc29. Your if statement checks to see if #c0ecc29 is a child component of target. It won't be, so the Check object with reference #c0ecc29 is added to target.
The second time the clickHandler is called, a new instance of the Check object is created which will have a new reference id. Your target has the original Check object with the #c0ecc29 reference so it won't get removed.
The correct way to get this working depends on what target is (DataGrid, Group, etc.).
EDIT:
Based on your comments, I would try something like this. It checks to see if the Check object is a child of target and adds it if needed. Then when the Check object is clicked, it will toggle its visibility.
public var check:Check = new Check();
private function seatClickHandler(e:MouseEvent):void
{
if(!e.target.contains(check))
{
check.addEventListener(MouseEvent.CLICK, check_handleClick);
e.target.addChild(check);
}
}
protected function check_handleClick(event:MouseEvent):void
{
check.visible = !check.visible;
}
If you need to actually remove the Check object from target instead of just changing its visibility, you could try this:
public var check:Check = new Check();
private function seatClickHandler(e:MouseEvent):void
{
if(!e.target.contains(check))
{
e.target.addChild(check);
}
else
{
e.target.removeChild(check);
}
}
If the child is named 'check' then you should be able to use getChildByName(). See flash.display.DisplayObject.name
If you happen to have the child in memory, you can use getChildIndex()
check is a new object in the scope of that function, so it will not be a child of the event target.
What you want to do is declare check as a global variable (And also cast target as DisplayObjectContainer).
e.g.
private function seatClickHandler(e:MouseEvent):void{
if((e.target as DisplayObjectContainer).contains(check)){
(e.target as DisplayObjectContainer).removeChild(seat);
}else{
(e.target as DisplayObjectContainer).addChild(check);
}
}
However I'm not sure if this is exactly what you want to do (There can only be one check). A better approach would be to have a function (maybe toggleCheck) on the target, and have that display object responsible for rendering the check (And removing it)
This worked perfectly fine for me in my situation:
if(possibleChild.parent == holder)
holder.removeChild(possibleChild)
It may or may not be exactly what you're looking for.

Can I specify a delay before the browser raises "rollover" event?

I am working on an ASP.NET web application that is required to bring up a popup on a roolover. I am using the "OnMouseOver" event and it works as expected. The problem is that the event is on a "hair trigger"; even a casual passage of the mouse over the control brings up the popup (which then must be manually dismissed). I want to add a delay so that a rapid pass over the control in question does not trigger the event. Is there a way to set such a delay or is there a different event that I could use to get the same "trigger event on a slow rollover"?
One solution that comes to mind, there may be better ways though:
Make the onmouseover call the function via a setTimeout delay
Inside the function, check the mouse is actually over that element.
You could also use an onmouseout to clear the setTimeout, but then you'd have to store a reference to the timer in a global variable to get at it again.
What I ended up doing is as follows (oRow is a table row but it could be any control):
function ItemMouseOver(oRow, "parameters for the popup")
{
oRow.showTimer = window.setTimeout(function()
{
alert('popup');
}, 1000);
}
function ItemMouseOut(oRow)
{
if (oRow.showTimer)
window.clearTimeout(oRow.showTimer);
In the ASP.NET grid view RowDataBound event: I added the following code:
protected void ReportGridView_RowDataBound(object sender, GridViewRowEventArgs e)
{
if (e.Row.RowType == DataControlRowType.DataRow && (
e.Row.RowState == DataControlRowState.Normal
|| e.Row.RowState == DataControlRowState.Alternate))
{
// get the input values for the popup for the row (stuff deleted)
e.Row.Attributes["onmouseover"] = "javascript:ItemMouseOver(this,
"parameters for the popup");";
e.Row.Attributes["onmouseout"] = "javascript:ItemMouseOut(this);";
}
}
It works just fine. Thanks.