CCScrollView returns one children - cocos2d-x

I am working on cocos2dx 3.0, and working on cocos2d::extension::ScrollView, getting a strange problem, is the scrollview doesn't return all the Nodes added to it, just returns one child, that too a different one.. See my code below
void Characters::setupScroll(){
Size winSize = Director::getInstance()->getWinSize();
if(!scrollView){
scrollView=cocos2d::extension::ScrollView::create(Size(winSize.width*1.0,winSize.height*0.8));
scrollView->setDirection(cocos2d::extension::ScrollView::Direction::HORIZONTAL);
scrollView->setPosition(Vec2(winSize.width*0.0,winSize.height*0.0));
this->addChild(scrollView);
scrollView->setClippingToBounds(true);
scrollView->setBounceable(true);
scrollView->setTouchEnabled(true);
}
float x=0.20;
for(int i=0;i<4;i++){
CharacterCell *cell=CharacterCell::createCell((kPlayer)i, CC_CALLBACK_1(Characters::chooseCharacterCallback, this));
Vec2 pos=Vec2(winSize.width*x,winSize.height*0.3);
cell->setPosition(pos);
x=x+0.35;
scrollView->addChild(cell);
cell->setTag(100+i);
cell->setScale(.9);
}
scrollView->setContentSize(Size(winSize.width*x,0.0));
}
Now on each cell selection I am doing see below
void Characters::chooseCharacterCallback(Ref *sender){
CharacterCell *cell=(CharacterCell *)sender;
//HERE I GET 1 AS CHILDREN COUNT
printf("%zd",scrollView->getChildrenCount());
Vector<Node*> cells=scrollView->getChildren();
for(int i=0;i<scrollView->getChildrenCount();i++){
CharacterCell *iCell=(CharacterCell *)cells.at(i);
iCell->setScale(0.9);
}
auto scaleup=ScaleTo::create(.3, 1.15);
auto ease=EaseBackIn::create(scaleup->clone());
cell->runAction(ease);
}
In the chooseCharacterCallback callback function below line gives children count as 1.
printf("%zd",scrollView->getChildrenCount());
Whereas surprisingly below line removes all the children.
scrollView->removeAllChildren();
This is an unusual behaviour, can any help me to get out of this?
Thanks.

The scroll view's only child is the "content node". You should not be adding or getting children to/from the scroll view directly, instead add a content node via the contentNode property and add and get children from that content node.

Related

Add "+5" if there is no space for more elements

I have a div (ItemsContainer) that has an array of items (Item) being rendered inside of it. The div has a dynamic size, depending on the size of the screen.
As I'm mapping through the array, I'd like to be able to make a check to see if there is enough space to render the current item. If there isn't, I'd like to stop rendering the items and instead add another item that says "+(number of items not rendered in array)". See the included picture for reference.
So far, this is what my code looks like. I'm using React typescript. I haven't attempted adding the "+5" box yet, because I'm wondering if it's actually possible? My initial thought is to just have a fixed number of items be displayed and then display the + item if there are more items not rendered, but I was hoping you could do it a bit more dynamic.
const Items: FC<Props> = ({ items }) => {
return (
<ItemsContainer>
{items.map((item, index) => (
<Item key={index}>{item.name}</Item>
))}
</ItemsContainer>
);
};
Here is a partially working solution: https://codepen.io/Latcarf/pen/WNKZmBN.
The main part of the code is the following:
const Tags = ({tags}) => {
const [hiddenCount, setHiddenCount] = React.useState(0)
const shownTags = hiddenCount == 0 ? tags : tags.slice(0, -hiddenCount);
const ref = React.useRef();
React.useLayoutEffect(() => {
if (!ref.current) {
return;
}
if (ref.current.scrollWidth > ref.current.clientWidth) {
setHiddenCount(count => count + 1);
}
});
return (
<div class="container" ref={ref}>
{shownTags.map(tag => <div class="tag">{tag}</div>)}
{hiddenCount > 0 && <div class="tag">{`+${hiddenCount}`}</div>}
</div>
)
};
The idea is to keep a hiddenCount state variable that contains the number of hidden tags. It starts at 0, and then a layout effect checks whether there is space and keeps incrementing it until there is enough space. It's a bit inefficient if you have many hidden items, as it will rerender many times until it reaches the correct amount, but it should properly deal with edge cases like if adding +1 would actually be longer than displaying the last tag, or stuff like that.
In order to make it update automatically on resize, you would use some kind of useResizeObserver hook to reset hiddenCount to 0 after a resize. Somehow I couldn’t manage to import other packages in CodePen, so I just made a button that forces a rerender so that you can test it (resize the div and then click the button).

Removing leaves that are between nodes in a JTree

Let's assume that I have a JTree similar to the picture I provided, in which the number of leaves and nodes will vary every time I run the code. Now how could I remove the nodes that are empty (AKA have no children) since I can't check so see if its going to be empty as I add them to the tree?
I have tried using an enumeration to traverse the tree and check for every node to check how many children it has but that didn't help because even if I could tell that the node I am at is a node that needs to be removed I have to tell his parent to remove him I cant tell him to remove himself from his parent node.
What do I need to use to achieve what I am looking for?
Now how could I remove the nodes that are empty...so i want a node to either have only other nodes or only leaves but not both at the same time
Traverse the tree and check for nodes which have the following criteria
Is a leaf
Has siblings that are not leafs.
even if I could tell that the node I am at is a node that needs to be removed I have to tell his parent to remove him I cant tell him to remove himself from his parent node.
That is what the DefaultTreeModel.removeNodeFromParent() method does. So you can traverse the tree recursively and just remove nodes based upon your given criteria.
DefaultMutableTreeNode root = new DefaultMutableTreeNode ("Root");
//other code
DefaultTreeModel treeModel = new DefaultTreeModel(root);
JTree tree = new JTree(treeModel);
//populate tree
recurseTree(root, treeModel);
//method to recursively remove leaf nodes that have non-leaf siblings
private void recurseTree(MutableTreeNode node, DefaultTreeModel treeModel){
if ( node.isLeaf() ){
TreeNode parent = node.getParent();
for ( int i = 0; i < parent.getChildCount(); i++ ){
if ( !parent.getChildAt(i).isLeaf() ){
treeModel.removeNodeFromParent(node);
break;
}
}
}else{
for ( int i = 0; i < node.getChildCount(); i++ ){
recurseTree((MutableTreeNode)node.getChildAt(i), treeModel);
}
}
}
All this being said, it looks like a long route around the initial addition of those nodes. Without knowing the underlying data structure to populate the tree one can only guess as to how to go about preventing those nodes from being added in the first place.

Mootools get second class name

I see the method of getting second class name with jquery but how do I do it in mootools , my element is <li class="parent active">
I need to match full class name like li.parent.active and adjust height if that class is present I tried
$$('li').hasClass('parent active') or getProperty but all of them return true even if active is not present, if I add .parent.active I get
The expression is not a legal expression. now I must support mootols 1.1 ,1.2 ,1.3 working on CMS here so I started with the ugly one 1.1 version
this is how is actually needed
var holderdiv =$('mymenu');
if($$('li.parent.active')){holderdiv.setStyle({'height':'50px'});
if($$('li.parent.active') == true) returns true as in, it's truthy (defined, not null).
if you mean to say: is there at least one child element that has .parent and .active, you can do:
if (holderdiv.getElement("li.parent.active")) // at least one.
holderDiv.setStyle("height", 50); // setStyle uses a value pair, not an object.
if they are not children of holderdiv just do document.getElement or whateverElObj.getElement instead.
this will likely break in 1.11 due to old xpath stuff.
one way to do it so it works in all versions would be this (though you should only do this if MooTools.version is wrong due to performance cost of double loops):
var holderdiv = $("holderdiv");
if (holderdiv.getElements("li.parent").some(function(el){ return el.hasClass("active"); })) {
// at least one.
holderdiv.setStyle("height", 50);
}
the .some will run through all li.parent until it finds one that matches the condition (hasClass("active")) and then return boolean true else, false.
http://jsfiddle.net/dimitar/BqwAk/
if you need to keep a reference of the lis into a collection, use .filter instead:
var lis = holderdiv.getElements("li.parent").filter(function(el){
return el.hasClass("active");
});
if all have .parent and only one can be active, you don't really care so you can just do
if (holderdiv.getElement("li.active"))
or
if (holderdiv.getElement("li.active").hasClass("parent"))
... to double check if they don't all have .parent.
You could simply match all elements with both classes parent and active and set their style, MooTools makes that easy:
$$('li.parent.active').setStyle({'height':'50px'});

libxml2 - remove child, but not grandchildren

I'm using libxml2 to parse HTML. I want to remove certain formatting tags like <center>, while keeping their content (for example, a link).
This means I'll have to remove certain child nodes from my xmlNodeSet, but keep that node's children.
Right now, I got this code:
xmlNodePtr parentNode = nodes->nodeTab[i];
if (parentNode != NULL) {
xmlNodePtr child = parentNode->children;
xmlNodePtr parentNextSibling = parentNode->next;
xmlNodePtr grandParent = NULL;
while (child) {
xmlUnlinkNode(child);
if (parentNextSibling != NULL) {
xmlAddPrevSibling(parentNextSibling, child);
}
else {
if (grandParent == NULL)
grandParent = parentNode->parent;
xmlAddChild(grandParent, child);
}
child = child->next;
}
xmlUnlinkNode(parentNode);
xmlFree(parentNode);
}
The code does add the child to the document, but it also deletes the node I was adding it as a sibling to. What am I doing wrong?
You're not saving off the child->next pointer before you cut it out of the tree. As soon as you unlink a node, it isn't part of the tree, so child->next becomes NULL. Then, after you reinsert it into the tree (before parentNode->next), the child->next pointer now points to what was previously parentNode->next, so the next time through the loop, you delete parentNode->next. Things can only go downhill from there. :-)

Show "no rows found" inside a JTable row if not found entry while filtering

i have a JTable with row filter.
once fitered if i didn't get any row then i have to show a string like "Nothing found to display " inside table as first row.
please do needful.
Thanks ,
Narasimha
I needed to solve this exact problem today and wasn't able to find a good answer online. In the end I came up with my own solution, which I think may be exactly what you want. I don't know if this is too late for your project, but perhaps it can help others:
JTable.paintComponent(Graphics g) will not be called unless the table has a height that is greater than 0. This causes a problem for empty tables, so we expand the JTable height if needed so that it will always be at least the size of the JViewport that is it's parent.
JTable tableName = new JTable() {
public boolean getScrollableTracksViewportHeight() {
if(getParent() instanceof JViewport)
return(((JViewport)getParent()).getHeight() > getPreferredSize().height);
return super.getScrollableTracksViewportHeight();
}
protected void paintComponent(Graphics g) {
super.paintComponent(g);
if(getRowCount() == 0) {
Graphics2D g2d = (Graphics2D) g;
g2d.setColor(Color.BLACK);
g2d.drawString("Nothing found to display.",10,20);
}
}
}
containerName.add(new JScrollPane(tableName));
To show a line of text in the multicolumn table can be quite difficult, the span AFAIK is not supported.
One possibility would be to hide all data columns (to show them later you have to memorize them somewhere) and show one column for the message.
An easier way would be to create a JPanel with CardLayout, add 2 cards - one containing table and one containing your empty data warning. If the filter returns empty result, show the card with empty warning, in other case - show the table.
If the filter has excluded all rows, the result returned by getViewRowCount() will be zero. You can update the GUI accordingly; setToolTipText() is handy if screen space is lacking.
Here's an example:
TableModel model = ...
JTable table = new JTable(model);
TableRowSorter<TableModel> sorter = new TableRowSorter<TableModel>(model);
table.setRowSorter(sorter);
JScrollPane pane = new JScrollPane(table);
JLabel label = new JLabel("");
...
String s = "Rows: " + sorter.getViewRowCount()
pane.setToolTipText(s);
label.setText(s);