MQL4 Drawing a Dynamic Rectangle_Label with a Text in It - object

I am trying to draw a Rectangle Label with a text in it every tick.. I want a text to fit exactly in to a Rectangle_Label.. As a text i am using Label.. But cant get it to work exactly.. It is not correctly situated..
In Fact i would like to create a class that would do it all in one... Just like a rectangle with text in it that would be always having same co ordinance and size etc..
Any help would be greatly appreciated...
bool createRectangleLabel(long chart_ID,string name,string labelName,int shift,double price,string text,double xSize,double ySize,double xOffSet,double yOffSet,double xDistance,double yDistance)
{
if(ObjectCreate(chart_ID,labelName,OBJ_RECTANGLE_LABEL,0,TimeCurrent()-shift,price))
{
Print(xDistance+" "+yDistance);
ObjectSetInteger(chart_ID,labelName,OBJPROP_BGCOLOR,clrBlack);
ObjectSetInteger(chart_ID,labelName,OBJPROP_XDISTANCE,xDistance);
ObjectSetInteger(chart_ID,labelName,OBJPROP_YDISTANCE,yDistance);
ObjectSetInteger(chart_ID,labelName,OBJPROP_YSIZE,ySize);
ObjectSetInteger(chart_ID,labelName,OBJPROP_XSIZE,xSize);
ObjectSetString(chart_ID,labelName,OBJPROP_TEXT,text);
ObjectSetInteger(chart_ID,name,OBJPROP_ANCHOR,ANCHOR_CENTER);
return true;
}
else
{
Print("createRectangleLabel return error code: ",GetLastError());
Print("+--------------------------------------------------------------+");
return false;
}
}
bool createLineText(long chart_ID,string name,string labelName,int shift,double price,string text)
{
int xDistance=0;
int yDistance=0;
int xSize,xOffSet;
int ySize,yOffSet;
bool i=ChartTimePriceToXY(chart_ID,0,TimeCurrent(),price,xDistance,yDistance);
if(ObjectCreate(chart_ID,name,OBJ_LABEL,0,TimeCurrent()-shift,price))
{
ObjectSetInteger(chart_ID,name,OBJPROP_BGCOLOR,clrWhite);
ObjectSetInteger(chart_ID,name,OBJPROP_XDISTANCE,xDistance);
ObjectSetInteger(chart_ID,name,OBJPROP_YDISTANCE,yDistance);
ObjectSetString(chart_ID,name,OBJPROP_TEXT,text);
ObjectSetInteger(chart_ID,name,OBJPROP_ANCHOR,ANCHOR_CENTER);
ObjectSetInteger(chart_ID,name,OBJPROP_COLOR,clrWhite);
ObjectSetInteger(chart_ID,name,OBJPROP_FONTSIZE,10);
xSize = ObjectGet(name,OBJPROP_XSIZE);
ySize = ObjectGet(name,OBJPROP_YSIZE);
xOffSet = ObjectGet(name,OBJPROP_XOFFSET);
yOffSet = ObjectGet(name,OBJPROP_YOFFSET);
TextGetSize(name,xSize,ySize);
createRectangleLabel(chart_ID,name,labelName,shift,price,text,xSize,ySize,xOffSet,yOffSet,xDistance,yDistance);
return true;
}
else
{
Print("createLineText return error code: ",GetLastError());
Print("+--------------------------------------------------------------+");
return false;
}
}

You cannot call ObjectCreate() every tick - it would return an error 4200.
If you check the object exists before creating, that would help. Alternative approach would be to try to create the object and assign it with some necessary properties (e.g., color of the object, anchor etc) in one block, and move it in another.
if(ObjectFind(chart_id,labelName)<0){
if(ObjectCreate(chart_ID,labelName,OBJ_RECTANGLE_LABEL,0,TimeCurrent()-shift,price)){
ObjectSetInteger(chart_ID,labelName,OBJPROP_BGCOLOR,clrBlack);//etc.
}
ObjectSetInteger(chart_ID,labelName,OBJPROP_XDISTANCE,xDistance);
ObjectSetInteger(chart_ID,labelName,OBJPROP_YDISTANCE,yDistance);//if you need to move the object or take other steps each tick, e.g. update text - do it here
}

You're thinking along the right lines when you say that you'd like to create a class. Fortunately for you, the standard library already includes all the classes you need to make chart objects. Documentation
Example Indicator:
#property strict
#property indicator_chart_window
#include <ChartObjects\ChartObjectsTxtControls.mqh>
class MyRectLabel : public CChartObjectRectLabel
{
CChartObjectLabel m_label;
public:
bool Create(long chart, const string name, const int window,
const int X, const int Y, const int sizeX, const int sizeY)
{
if(!CChartObjectRectLabel::Create(chart,name,window,X,Y,sizeX,sizeY))
return false;
return m_label.Create(chart, name + "_", window, X + 8, Y + 12);
}
bool Color(const color clr){
return m_label.Color(clr);
}
bool Description(const string text){
return m_label.Description(text);
}
bool FontSize(const int size){
return m_label.FontSize(size);
}
bool ToolTip(const string text){
return (this.ToolTip(text) && m_label.Tooltip(text));
}
};
//+------------------------------------------------------------------+
MyRectLabel rect_label;
//+------------------------------------------------------------------+
int OnInit()
{
if(!rect_label.Create(0, "rlabel", 0, 5, 25, 100, 50)
|| !rect_label.BackColor(clrWhiteSmoke)
|| !rect_label.Description("LABEL!")
|| !rect_label.Tooltip("I am a rectangle label")
|| !rect_label.Color(clrBlack)
|| !rect_label.FontSize(18)
)
return INIT_FAILED;
return INIT_SUCCEEDED;
}
//+------------------------------------------------------------------+
int start()
{
static double last_price = 0.;
rect_label.Description(DoubleToString(Bid, _Digits));
if(Bid > last_price)
rect_label.Color(clrLimeGreen);
else
rect_label.Color(clrRed);
last_price = Bid;
return 0;
}

Related

Calling a String in Processing

I'm new to processing/java/code but was hoping for some help with my sketch.
I am trying to create an ink-looking sketch, with letters/characters displayed, then faded out instead of particles themselves. Inspired by https://openprocessing.org/sketch/1576908 I've run into errors with the entire particle constructor with an error on the line void update(p):
//update the velocity and location of particle
void update(p){
this.acceleration.add(createVector((noise(this.location.x)*2-1), (noise(this.location.y)*2-1)));
this.velocity.add(this.acceleration);
this.acceleration.set(0,0);
this.location.add(this.velocity);
this.alpha -= this.rate ;
// here is the recursion condition
if(this.alpha<=this.palpha*0.25 && this.palpha>10) {
p.push(new particle(this.location.x, this.location.y, this.rate*0.25, this.palpha*0.5));
}
}
Here is my full code
Thank you!
String[] particles = {"a", "b", "c", "d"} ; //string of particles
int velocity;
int acceleration;
int location;
int alpha;
int p;
void setup() {
size(600, 600);
background(255);
}
void draw() {
if(mousePressed) {
// spawn a new particle and add it to the array
particles.push(text(particles, mouseX, mouseY, 75));
textSize(random(20, 40));
}
// update and show the particles
for(int i=particles.length-2; i>=0; i--) {
particles[i].update(particles);
particles[i].show();
if(particles[i].alpha<=2) particles.splice(i, 5); // remove the dead particle
}
}
//particle class
class particle{
//constructor called when creating an instance of this class
// x & y are the location, r is the rate of decay, a is the starting alpha value
particle(float x, float y, float r, float a){
this.location = createVector(x,y) ;
this.velocity = createVector(random(-1,1),random(-1,1));
this.acceleration = createVector();
this.alpha = this.palpha=a ;
this.amp=4; // size of the particle
this.rate = r;
}
//update the velocity and location of particle
void update(p){
this.acceleration.add(createVector((noise(this.location.x)*2-1), (noise(this.location.y)*2-1)));
this.velocity.add(this.acceleration);
this.acceleration.set(0,0);
this.location.add(this.velocity);
this.alpha -= this.rate ;
// here is the recursion condition
if(this.alpha<=this.palpha*0.25 && this.palpha>10) {
p.push(new particle(this.location.x, this.location.y, this.rate*0.25, this.palpha*0.5));
}
}
//show the particles
void show(){
noStroke() ;
fill(0,35,25, this.alpha) ;
ellipse(this.location.x, this.location.y, this.amp);
}
} // end particle class```
You have at least two separate questions here:
how to port the p5.js sketch to Processing ?
how to add text for each particle ?
In the future I recommend breaking the problem down to simpler/shorter problems that can be tackle independently.
How let's look at the syntax errors Processing presents:
1.
particles.push(text(particles, mouseX, mouseY, 75));
errors with
The function "text()" expects parameters like: "text(int, float, float, float)"
The issue here is slightly masked. It looks like instead of calling text(yourTextString, yourTextX, yourTextY); you have different parameters. In reality there are two issues here:
push() is JavaScript Array's function. You need to use an ArrayList and its add() method instead in Processing (Java).
currently the particle class doesn't handle text. You can add a String text property which you can supply with a modified contructor: Particle(float x, float y, float r, float a, String text) (and you'd assign the constructor argument to the instance property (e.g. this.text = textl)
createVector exists in p5.js. In Processing you can switch this to new PVector(). Additionally you need to declare the variables initialised in the constructor as part of the class (e.g. location, velocity, acceleration, alpha, palpha, amp, rate).
ellipse(this.location.x, this.location.y, this.amp); is missing the last argument: ellipse(this.location.x, this.location.y, this.amp, this.amp);
This is a modified version of your code with the above notes applied:
// original sketch by OpenProcessing user Prasad
// https://openprocessing.org/sketch/1576908
String[] particlesText = {"a", "b", "c", "d"} ; //string of text
// array of particles
ArrayList<Particle> particles = new ArrayList<Particle>();
int velocity;
int acceleration;
int location;
int alpha;
int p;
void setup() {
size(600, 600);
background(255);
}
void draw() {
if(mousePressed) {
// spawn a new particle and add it to the array
// use % to loop over text (e.g .a,b,c,d,a...etc)
int textIndex = particles.size() % particlesText.length;
// grab the text from the array
String text = particlesText[textIndex];
// add a new particle providing text as well
particles.add(new Particle((float)mouseX, (float)mouseY,5.0, 75.0, text));
textSize(random(20, 40));
}
// update and show the particles
for(int i=particles.size()-2; i>=0; i--) {
Particle particle = particles.get(i);
particle.update(particles);
particle.show();
if(particle.alpha<=2) particles.remove(i); // remove the dead particle
}
}
//particle class
class Particle{
PVector location;
PVector velocity;
PVector acceleration;
float alpha;
float palpha;
float amp;
float rate;
String text = "";
//constructor called when creating an instance of this class
// x & y are the location, r is the rate of decay, a is the starting alpha value
Particle(float x, float y, float r, float a, String text){
this.location = new PVector(x,y) ;
this.velocity = new PVector(random(-1,1),random(-1,1));
this.acceleration = new PVector();
this.alpha = this.palpha=a ;
this.amp=4; // size of the particle
this.rate = r;
this.text = text;
}
//update the velocity and location of particle
void update(ArrayList<Particle> p){
this.acceleration.add(new PVector((noise(this.location.x)*2-1), (noise(this.location.y)*2-1)));
this.velocity.add(this.acceleration);
this.acceleration.set(0,0);
this.location.add(this.velocity);
this.alpha -= this.rate ;
// here is the recursion condition
if(this.alpha<=this.palpha*0.25 && this.palpha>10) {
p.add(new Particle(this.location.x, this.location.y, this.rate*0.25, this.palpha*0.5, this.text));
}
}
//show the particles
void show(){
noStroke() ;
fill(0,35,25, this.alpha);
//render the ellipse
ellipse(this.location.x, this.location.y, this.amp, this.amp);
// render the text
textSize(this.amp * 6);
text(this.text, this.location.x, this.location.y);
}
} // end particle class
(Note that you can choose not to render the ellipses and you can tweak the text size to something that makes more sense aesthetically. Also, when you're using other people's code, always credit them.)

Processing PApplet call in nested classes

I'm using Processing 3 to make a GUI for a servo controller instead of using a pre-made library. It's based on having a packaging class organize several subclasses which use registerMethod mouse events to operate (as opposed to the simpler use of mousePressed() in the main sketch). What I'm getting hung up on is the PApplet naming/terms for each class to ensure that they can function both inside a subclass as well as on their own when called from the main. In my example the package is just a single button, as well as a direct button call for comparison. I do know that most current Java-users consider Applet use outdated, but since I'm just using the Processing IDE, I'd like to understand this concept better as well as try to avoid using something more complicated (but maybe less confusing) like an Interface.
PackServ tryMe;
Butt bOne;
void setup() {
size(200, 150);
tryMe = new PackServ(this);
bOne = new Butt(this);
}
void draw() {
background (250);
tryMe.Add(20, 10, 50);
line(100,10,100,100);
fill(130,255,170);
rect(120,10,50,60,5);
bOne.Add("B2", 145,35,25);
stroke(20); textSize(14); fill(25);
text("single", 130,100);
text("package", 20,100);
}
public class PackServ extends PApplet {
PApplet SerApp;
Butt Butt1, Butt2;
String theName;
int pkX, pkY, pkW;
PackServ(PApplet pa) {
this.SerApp = pa;
theName = "The Slider";
pkX = 20;
pkY = 20;
pkW = 100;
}
void Add(int _x, int _y, int _w) {
pkX = _x; pkY = _y; pkW = _w;
Butt1 = new Butt (this);
drawIt();
}
void drawIt() {
SerApp.fill(200);
SerApp.strokeWeight(1);
SerApp.rect(pkX, pkY, pkW, 60, 5);
Butt1.Add("B1", pkX+25, pkY+25, 25);
}
}
public class Butt
{
PApplet butApp;
int theX, theY, theW, theH, bRad;
boolean pressed = false;
color n;
color h = color(240, 210, 10);
color f = color (40, 90, 190);
color a = color (240, 20, 20);
int oBb, li;
String theLabel;
Butt (PApplet butApplet) {
this.butApp = butApplet;
butApp.registerMethod("mouseEvent",this);
n = f;
}
void Add(String _myName, int x, int y, int siz) {
theLabel = _myName;
theX = x;
theY = y;
bRad = siz;
fill(75);
textSize(9);
buttonLook();
}
boolean overB(int mx, int my) {
if (dist (mx, my, theX, theY) <= bRad) {
return true;
} else {
return false;
}
}
void buttonLook() {
if (overB(mouseX, mouseY) && pressed) {
n = a;
oBb = 3; li = 100;
} else if (overB(mouseX, mouseY)) {
text(theLabel, theX-10, theY+25);
n = h;
} else {
n = f; oBb=1; li=25;
}
strokeWeight(oBb);
stroke(li);
fill(n);
ellipse(theX, theY, bRad, bRad);
}
void mouseEvent(MouseEvent e) {
pressed = false;
int mx = e.getX(), my = e.getY();
switch (e.getAction()) {
case MouseEvent.PRESS:
pressed = overB(mx, my);
break;
}
}
}
I'm not totally sure what you're asking, so let me try to answer a few different things that you seem a bit confused about.
I do know that most current Java-users consider Applet use outdated
Please note that other than its name, PApplet has nothing to do with applets. Historically a PApplet was an applet, but as of Processing 3 that's no longer the case. PApplet is its own thing and has nothing to do with applets.
Let's take a closer look at this code:
public class PackServ extends PApplet {
PApplet SerApp;
PackServ(PApplet pa) {
this.SerApp = pa;
...
It doesn't make a ton of sense to extend PApplet and also take a PApplet argument into the constructor. This means that you now have two PApplet instances, which is almost never what you want to do.
Instead, my guess is you probably want to get rid of the extends PApplet part and only use Processing's classes using your serApp variable.
I believe that's the crux of your confusion: the PApplet class offers a bunch of handy functions like draw() and ellipse(), basically most variables and functions in the Processing reference. So you do need an instance of PApplet, but that instance is created for you when you use the Processing editor. You don't need to create your own instance by extending the PApplet class.

unordered_map insertion is creating bottleneck

So here I am trying to create a Graph data structure in which i have to keep track of edges according to their ids. So I am creating edge ids in string data structure as eid: sourceid_destinationid
using namespace std;
class Edge{
public:
bool operator==(const Edge* &obj) const
{
return eid==obj->eid;
}
std::string eid;
set<int> rrids;
int sourceid;
int destid;
int strength;
public:
Edge(std::string eid,int from,int to);
std::string getId();
void addRRid(int rrid);
void removeRRid(int rrid);
void setRRid(set<int> rrids);
void setId(std::string eid);
};
This is another class which I am using for adding and removing the edges.
hpp-file
using namespace std;
class RRassociatedGraph{
public:
unordered_map<int,vertex*> vertexMap;
std::unordered_map<std::string,Edge*> EdgeMap;
int noOfEdges;
public:
RRassociatedGraph();
unordered_set<vertex> getVertices();
int getNumberOfVertices();
void addVertex(vertex v);
vertex* find(int id);
Edge* findedge(std::string id);
void addEdge(int from, int to, int label);
void removeEdge(int from, int to,int rrSetID);
};
When I debugged the code I found out that in the function add edge here the place where I am doing EdgeMap.insert the execution doesn't go to next line. It remains in hashtable for loop of some bucket entry. I can't debug this code frequently because I have to wait for 3 hours to get this issue. The code is working perfectly with small graphs. But for larger graphs where edgeMap has to store 800k edges. It goes in this hashtable infinite loop. I don't get this hashtable code. But is there something wrong with my data structure of creating Edgemap?
#include "RRassociatedGraph.hpp"
RRassociatedGraph::RRassociatedGraph() {
noOfEdges=0;
}
void RRassociatedGraph::addVertex(vertex v) {
vertexMap.insert(pair<int,vertex*>(v.getId(), &v));
}
vertex* RRassociatedGraph::find(int id) {
unordered_map<int,vertex*>::const_iterator got=vertexMap.find(id);
if(got != vertexMap.end() )
return got->second;
return nullptr;
}
Edge* RRassociatedGraph::findedge(std::string id){
unordered_map<std::string,Edge*>::const_iterator got=EdgeMap.find(id);
if(got != EdgeMap.end() )
return got->second;
return nullptr;
}
void RRassociatedGraph::addEdge(int from, int to, int label) {
vertex* fromVertex = find(from);
if (fromVertex == nullptr) {
fromVertex = new vertex(from);
vertexMap.insert(pair<int,vertex*>(fromVertex->getId(), fromVertex));
}
vertex* toVertex = find(to);
if (toVertex == nullptr) {
toVertex = new vertex(to);
vertexMap.insert(pair<int,vertex*>(toVertex->getId(), toVertex));
}
if(fromVertex==toVertex){
// fromVertex->outDegree++;
//cout<<fromVertex->getId()<<" "<<toVertex->getId()<<"\n";
return;
}
std::string eid=std::to_string(from);
eid+="_"+std::to_string(to);
Edge* edge=findedge(eid);
if(edge==nullptr){
edge=new Edge(eid,from,to);
edge->addRRid(label);
fromVertex->addOutGoingEdges(edge);
EdgeMap.insert(pair<std::string,Edge*>(edge->getId(), edge));
noOfEdges++;
}
else{
edge->addRRid(label);
fromVertex->outDegree++;
}
}
void RRassociatedGraph::removeEdge(int from, int to,int rrSetID) {
vertex* fromVertex = find(from);
std::string eid=std::to_string(from);
eid+="_"+std::to_string(to);
if(EdgeMap.count(eid)==1){
Edge* e=EdgeMap.find(eid)->second;
if(fromVertex->removeOutgoingEdge(e,rrSetID)){
EdgeMap.erase(eid);
delete e;
}
}
}
this is the place where it keeps going into this for loop. The insertion time of map should be very less but this is creating bottleneck in my code.
template <class _Tp, class _Hash, class _Equal, class _Alloc>
void
__hash_table<_Tp, _Hash, _Equal, _Alloc>::__rehash(size_type __nbc)
{
#if _LIBCPP_DEBUG_LEVEL >= 2
__get_db()->__invalidate_all(this);
#endif // _LIBCPP_DEBUG_LEVEL >= 2
__pointer_allocator& __npa = __bucket_list_.get_deleter().__alloc();
__bucket_list_.reset(__nbc > 0 ?
__pointer_alloc_traits::allocate(__npa, __nbc) : nullptr);
__bucket_list_.get_deleter().size() = __nbc;
if (__nbc > 0)
{
for (size_type __i = 0; __i < __nbc; ++__i)
__bucket_list_[__i] = nullptr;
__next_pointer __pp = __p1_.first().__ptr();
__next_pointer __cp = __pp->__next_;
if (__cp != nullptr)
{
size_type __chash = __constrain_hash(__cp->__hash(), __nbc);
__bucket_list_[__chash] = __pp;
size_type __phash = __chash;
for (__pp = __cp, __cp = __cp->__next_; __cp != nullptr;
__cp = __pp->__next_)
{
__chash = __constrain_hash(__cp->__hash(), __nbc);
if (__chash == __phash)
__pp = __cp;
else
{
if (__bucket_list_[__chash] == nullptr)
{
__bucket_list_[__chash] = __pp;
__pp = __cp;
__phash = __chash;
}
else
{
__next_pointer __np = __cp;
for (; __np->__next_ != nullptr &&
key_eq()(__cp->__upcast()->__value_,
__np->__next_->__upcast()->__value_);
__np = __np->__next_)
;
__pp->__next_ = __np->__next_;
__np->__next_ = __bucket_list_[__chash]->__next_;
__bucket_list_[__chash]->__next_ = __cp;
}
}
}
}
}
}
I have many files so I can't put the whole code. I am not that good in c++. Please let me know if I have to implement it some other way. I have to use hashMap because I also need faster search.
You are probably experiencing re-hash at insert. Unordered_map has number of buckets. When they are filled worst case insert time is O(size()).
http://en.cppreference.com/w/cpp/container/unordered_map/insert
Rehashing occurs only if the new number of elements is greater than max_load_factor()*bucket_count().
What you may do with your current setup is:
1. Growth map at the init of the program, as usually number of buckets doesn't shrink.
2. Change from std::unordered_map to Boost::intrusive_map, where you can manager number of buckets manually.

what's different between StrCmpW and wcscmp?

Actually i changed code to next.
struct myclass {
bool operator() (std::wstring p1, std::wstring p2) {
int result = 0;
//// If character is alphabet, sorting need converse.
wint_t a1 = p1.at(0);
wint_t b2 = p2.at(0);
int r1 = iswalpha(a1);
int r2 = iswalpha(b2);
**// return code of iswalpha.
// 257 is Upper Alphabet,
// 258 is Lower Alphabet**
if ((r1 == 257 && r1 == 258) ||
(r2 == 258 && r2 == 257)) {
result = p2.compare(p1);
}
else {
result = p1.compare(p2);
}
if (result != 0) {
if (result == -1) {
return true;
}
else {
return false;
}
}
return false;
}
} wStrCompare;
void main() {
std::vector<std::wstring> wlist;
wlist.emplace_back(L"가나");
wlist.emplace_back(L"123");
wlist.emplace_back(L"abc");
wlist.emplace_back(L"타파");
wlist.emplace_back(L"하하");
wlist.emplace_back(L"!##$");
wlist.emplace_back(L"一二三");
wlist.emplace_back(L"好好");
wlist.emplace_back(L"QWERID");
wlist.emplace_back(L"ⓐⓑ");
wlist.emplace_back(L"☆★");
wlist.emplace_back(L"とばす");
std::sort(wlist.begin(), wlist.end(), wStrCompare);
}
Test Result
L"!##$"
L"123"
L"abc"
L"QWERID"
L"ⓐⓑ"
L"☆★"
L"とばす"
L"一二三"
L"好好"
L"가나"
L"타파"
L"하하"
is this good?
Please give me a some opinion.
Thanks!!
I change my code, but i still want to know "is there difference between StrCmpW and wcscmp" Please talk to me. thanks!
Old question
I use qsort with std::wstring(for unicode string), and use StrCmpW.
Previously, I used StrCmpLogicalW() with CString, CStringArray.
(These are depend on windows)
But my code run in linux too, not only in windows.
(CString is ATL(afx), StrCmpLogicalW() is in Shlwapi.h)
So I use std::wstring and wcscmp, but result is different.
Is there a difference between StrCmpW() and wcscmp()?
The Following is my code.(exactly not mine lol)
int wCmpName(const void* p1, const void *p2)
{
std::wstring* wszName1 = ((std::wstring *)(p1));
std::wstring* wszName2 = ((std::wstring *)(p2));
int wret = StrCmpW(wszName1->c_str(), wszName2->c_str());
// int wret = wcscmp(wszName1->c_str(), wszName2->c_str());
// When i use wcscmp, different result comes out.
return wret;
}
void wSort(std::vector<std::wstring> &arr)
{
qsort(arr.data(), arr.size(), sizeof(std::wstring), wCmpName);
}
Thanks!
Test Code
void main() {
std::vector<std::wstring> wlist;
wlist.emplace_back(L"가나");
wlist.emplace_back(L"123");
wlist.emplace_back(L"abc");
wlist.emplace_back(L"타파");
wlist.emplace_back(L"하하");
wlist.emplace_back(L"!##$");
wlist.emplace_back(L"一二三");
wlist.emplace_back(L"好好");
wlist.emplace_back(L"QWERID");
wlist.emplace_back(L"ⓐⓑ");
wlist.emplace_back(L"☆★");
wlist.emplace_back(L"とばす");
wSort(wlist);
}
Test Result
wcscmp
L"!##$"
L"123"
L"QWERID"
L"abc"
L"ⓐⓑ"
L"☆★"
L"とばす"
L"一二三"
L"好好"
L"가나"
L"타파"
L"하하"
StrCmpW
L"!##$"
L"☆★"
L"123"
L"ⓐⓑ"
L"abc"
L"QWERID"
L"とばす"
L"가나"
L"一二三"
L"타파"
L"하하"
L"好好"
p.s : WHY limit reputation?! limited Images, limited URLs.
Only text takes so long time.

ExpandableListView - onItemLongClick - getPackedPositionChild always returns 0

ExpandableListView.getPackedPositionChild(id) below is always returning 0. The group position is correct, but I can't get the correct child position. What's wrong with the code below?
#Override
public boolean onItemLongClick(AdapterView<?> parent, View view, int position, long id) {
if (ExpandableListView.getPackedPositionType(id) == ExpandableListView.PACKED_POSITION_TYPE_CHILD) {
int groupPosition = ExpandableListView.getPackedPositionGroup(id);
int childPosition = ExpandableListView.getPackedPositionChild(id);
// do something
return true;
}
return false;
}
A bit of addition code is needed. You must first convert the input Integer-based flat List position to a Long-based Packed Position. Tested code follows:
#Override
public boolean onItemLongClick( AdapterView<?> parent,
View view,
int position,
long id) {
// convert the input flat list position to a packed position
long packedPosition = m_expandableListView.getExpandableListPosition(position);
int itemType = ExpandableListView.getPackedPositionType(packedPosition);
int groupPosition = ExpandableListView.getPackedPositionGroup(packedPosition);
int childPosition = ExpandableListView.getPackedPositionChild(packedPosition);
// GROUP-item clicked
if (itemType == ExpandableListView.PACKED_POSITION_TYPE_GROUP) {
// ...
onGroupLongClick(groupPosition);
}
// CHILD-item clicked
else if (itemType == ExpandableListView.PACKED_POSITION_TYPE_CHILD) {
// ...
onChildLongClick(groupPosition, childPosition);
}
// return "true" to consume event - "false" to allow default processing
return false;
}

Resources