public override void onMouseUp(int x, int y)
        {
            if (viewState == VIEWSTATE_1_NHOMNGANH && chartG != null)
            {
                chartG.onMouseUp(x, y);
                return;
            }
            for (int i = 0; i < mButtonPositions.size(); i++)
            {
                Rectangle rc = (Rectangle)mButtonPositions.elementAt(i);
                if (rc.Contains(x, y))
                {
                    mPeriod = mPeriods.elementAt(i);

                    doCalcChanged();
                    return;
                }
            }

            for (int i = 0; i < mChanges.size(); i++)
            {
                GroupChanges gc = (GroupChanges)mChanges.elementAt(i);
                if (x >= gc.x && x <= gc.x + gc.w &&
                    y >= gc.y && y <= gc.y + gc.h)
                {
                    stShareGroup g = gc.group;
                    showDetailOfGroup(g);
                }
            }
        }
        void calcChanged(int period)
        {
            stCandle c0 = new stCandle();
            stCandle c1 = new stCandle();

            mChanges.removeAllElements();

            Utils.trace("----------------------");
            bool isNhomIndex = false;

            for (int i = 0; i < mGroups.size(); i++)
            {
                stShareGroup g  = (stShareGroup)mGroups.elementAt(i);
                GroupChanges gc = new GroupChanges();
                gc.group = g;
                mChanges.addElement(gc);
                gc.code = g.getName();

                Utils.trace(g.getName());

                double firstGTGD = 0;
                double lastGTGD  = 0;

                double totalGTGD0 = 0;
                double totalGTGD1 = 0;

                int today = 0;

                isNhomIndex = false;

                if (g.getType() == stShareGroup.ID_GROUP_MARKET_OVERVIEW &&
                    g.getTotal() == 1)
                {
                    isNhomIndex = true;
                    String code  = g.getCodeAt(0);
                    Share  share = mContext.mShareManager.getShare(code);
                    if (share == null)
                    {
                        continue;
                    }

                    share.loadShareFromFile(false);
                    share.appendTodayCandle2();

                    int last  = share.getCandleCnt() - 1;
                    int first = (last > period)?(last - period):0;
                    if (last < 0 || first < 0)
                    {
                        continue;
                    }

                    c0 = share.getCandle(last, c0);
                    c1 = share.getCandle(first, c1);

                    if (c1.close > 0)
                    {
                        double changed = 100 * (c0.close - c1.close) / c1.close;

                        gc.changedPercent += changed;
                    }

                    continue;
                }

                for (int j = 0; j < g.getTotal(); j++)
                {
                    string        code    = g.getCodeAt(j);
                    Share         share   = Context.getInstance().mShareManager.getShare(code);
                    int           shareID = Context.getInstance().mShareManager.getShareID(code);
                    stCompanyInfo info    = Context.getInstance().mShareManager.getCompanyInfo(shareID);
                    if (share != null && info != null)
                    {
                        share.loadShareFromCommonData(true);
                        int last  = share.getCandleCnt() - 1;
                        int first = (last > period)?(last - period):0;
                        if (last < 0 || first < 0)
                        {
                            continue;
                        }

                        share.getCandle(last, c0);
                        share.getCandle(first, c1);

                        double changed;
                        if (period == 1 && c0.date < today)
                        {
                            //  khong co giao dich hom nay
                            changed = 0;
                        }
                        else
                        {
                            double r = (info.volume * c1.close);
                            changed = 0;// (c0.close - c1.close) * r;

                            changed  = 100 * (c0.close - c1.close) / c1.close;
                            changed *= r;
                        }

                        totalGTGD0 += (c0.close * info.volume);
                        totalGTGD1 += (c1.close * info.volume);

                        gc.changedPercent += changed;
                        //String s = String.Format("Code: {0}, Price: Close0/Close1={1}/{2}, r={3} changed/totalChanged: {4}/{5}",
                        //share.getCode(), c0.close, c1.close, r, changed, gc.changedPercent);
                        //Utils.trace(s);
                    }

                    gc.changedPercent  = 100 * (totalGTGD0 - totalGTGD1);
                    gc.changedPercent /= totalGTGD1;
                }

                //Utils.trace(String.Format("Total changed: {0}", gc.changedPercent));
            }

            //  sort
            if (false)//isNhomIndex)
            {
                //  khong sort
            }
            else
            {
                xVector marketOverView = new xVector();
                for (int i = 0; i < mChanges.size() - 1; i++)
                {
                    GroupChanges g = (GroupChanges)mChanges.elementAt(i);
                    if (g.group.getType() == stShareGroup.ID_GROUP_MARKET_OVERVIEW || g.code.IndexOf('#') == 0)
                    {
                        marketOverView.addElement(g);
                    }
                }

                for (int i = 0; i < marketOverView.size(); i++)
                {
                    mChanges.removeElement(marketOverView.elementAt(i));
                }

                //================================

                for (int i = 0; i < mChanges.size() - 1; i++)
                {
                    GroupChanges biggest    = (GroupChanges)mChanges.elementAt(i);
                    int          biggestIdx = i;
                    for (int j = i + 1; j < mChanges.size(); j++)
                    {
                        GroupChanges gc = (GroupChanges)mChanges.elementAt(j);
                        if (gc.changedPercent > biggest.changedPercent)
                        {
                            biggest    = gc;
                            biggestIdx = j;
                        }
                    }

                    if (biggestIdx != i)
                    {
                        mChanges.swap(i, biggestIdx);
                    }
                }
                //========================
                for (int i = 0; i < mChanges.size(); i++)
                {
                    marketOverView.addElement(mChanges.elementAt(i));
                }
                mChanges.removeAllElements();
                for (int i = 0; i < marketOverView.size(); i++)
                {
                    mChanges.addElement(marketOverView.elementAt(i));
                }
            }
        }
        override public void render(xGraphics g)
        {
            //=========================
            if (viewState == VIEWSTATE_1_NHOMNGANH && chartG != null)
            {
                chartG.render(g);
                return;
            }

            g.setColor(C.COLOR_BLACK);
            g.clear();

            if (isProcessing)
            {
                g.setColor(C.COLOR_ORANGE);
                g.drawStringInRect(mContext.getFontSmallB(), "Đang xử lý", 0, 0, getW(), getH(), xGraphics.HCENTER | xGraphics.VCENTER);
                return;
            }

            //  title
            //      [Hom nay] [1 Tuan] [1 Thang] [3 thang] [1 nam]
            //          Tang          |          Giam          |
            //  VN30: +15%; GTDG: 30.1ti    .Chart
            //
            if (mChanges.size() == 0)
            {
                calcChanged(mPeriod);
            }
            if (mChanges.size() == 0)
            {
                return;
            }


            float x, y;
            int   buttonW = 80;
            int   buttonH = 26;

            int gap = 4;

            x = (getW() - 6 * (buttonW + gap)) / 2;

            //  button
            y = 2;
            mButtonPositions.removeAllElements();
            mPeriods.removeAllElements();
            string[] buttons = { "1 Ngày", "1 Tuần", "1 Tháng", "3 Tháng", "6 Tháng", "1 Năm" };
            int[]    periods = { 1, 5, 22, 67, 130, 260 };
            for (int i = 0; i < buttons.Length; i++)
            {
                string s = buttons[i];
                g.setColor(C.COLOR_GRAY_LIGHT);
                g.drawRect((int)x, 2, buttonW, buttonH);
                g.setColor(mPeriod == periods[i]?C.COLOR_ORANGE:C.COLOR_WHITE);
                g.drawStringInRect(mContext.getFontSmallB(), s, (int)x, (int)y, buttonW, buttonH, xGraphics.HCENTER | xGraphics.VCENTER);

                Rectangle rc = new Rectangle((int)x, 2, buttonW, buttonH);
                mButtonPositions.addElement(rc);
                mPeriods.addElement(periods[i]);

                x += buttonW + gap;
            }

            g.setColor(C.COLOR_GRAY_DARK);
            g.drawHorizontalLine(0, buttonH + 4, getW());

            int    columnH    = ItemH;
            double maxPercent = 0;

            for (int i = 0; i < mChanges.size(); i++)
            {
                GroupChanges gc = (GroupChanges)mChanges.elementAt(i);
                if (Math.Abs(gc.changedPercent) > maxPercent)
                {
                    maxPercent = Math.Abs(gc.changedPercent);
                }
            }
            //--------------------
            int buttonY = 30;
            int drawH   = getH() - buttonY;

            ItemH = getItemH(getH() - 40, mChanges.size());

            float cellW = getW() / 2;
            float cellH = ItemH;

            maxPercent *= 1.15;
            //  Left side
            int j = 0;

            y = buttonY + 4;

            int itemPerColumn = mChanges.size() / 2;

            for (int i = 0; i < itemPerColumn; i++)
            {
                GroupChanges gc = (GroupChanges)mChanges.elementAt(i);
                x = 2;
                //if (gc.changedPercent >= 0)
                {
                    y     = buttonY + 4 + j * cellH;
                    cellW = (float)((Math.Abs(gc.changedPercent) / maxPercent) * getW() / 2);
                    g.setColor(gc.changedPercent > 0?C.COLOR_GREEN_DARK:C.COLOR_RED);
                    g.fillRectF(x, y, cellW, cellH - 2);

                    //  text
                    g.setColor(C.COLOR_WHITE);
                    if (gc.changedPercent >= 0)
                    {
                        string s = String.Format("{0} +{1:F2} %", gc.code, gc.changedPercent);
                        g.drawString(mContext.getFontText(), s, (int)x, (int)(y + cellH / 2), xGraphics.VCENTER);
                    }
                    else
                    {
                        string s = String.Format("{0} {1:F2} %", gc.code, gc.changedPercent);
                        g.drawString(mContext.getFontText(), s, (int)x, (int)(y + cellH / 2), xGraphics.VCENTER);
                    }
                    j++;

                    gc.x = (int)x;
                    gc.y = (int)y;
                    gc.w = (int)getW() / 2 - 10;
                    gc.h = (int)cellH;
                }
            }
            g.setColor(C.COLOR_GRAY_DARK);
            g.drawVerticalLine(getW() / 2, buttonY, getH());
            //  Right side
            j = 0;
            for (int i = itemPerColumn; i < mChanges.size(); i++)
            {
                GroupChanges gc = (GroupChanges)mChanges.elementAt(i);
                x = getW() / 2 + 2;
                //if (gc.changedPercent < 0)
                {
                    y     = buttonY + 4 + j * cellH;
                    cellW = (float)((Math.Abs(gc.changedPercent) / maxPercent) * getW() / 2);
                    g.setColor(gc.changedPercent > 0 ? C.COLOR_GREEN_DARK : C.COLOR_RED);
                    g.fillRectF(x, y, cellW, cellH - 2);

                    //  text
                    g.setColor(C.COLOR_WHITE);
                    if (gc.changedPercent >= 0)
                    {
                        string s = String.Format("{0}: +{1:F2} %", gc.code, gc.changedPercent);
                        g.drawString(mContext.getFontText(), s, (int)x, (int)(y + cellH / 2), xGraphics.VCENTER);
                    }
                    else
                    {
                        string s = String.Format("{0}: {1:F2} %", gc.code, gc.changedPercent);
                        g.drawString(mContext.getFontText(), s, (int)x, (int)(y + cellH / 2), xGraphics.VCENTER);
                    }
                    j++;

                    gc.x = (int)x;
                    gc.y = (int)y;
                    gc.w = (int)getW() / 2 - 10;
                    gc.h = (int)cellH;
                }
            }
        }