edu.tsinghua.lumaqq.ui.helper.MenuHelper.java Source code

Java tutorial

Introduction

Here is the source code for edu.tsinghua.lumaqq.ui.helper.MenuHelper.java

Source

/*
* LumaQQ - Java QQ Client
*
* Copyright (C) 2004 luma <stubma@163.com>
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
package edu.tsinghua.lumaqq.ui.helper;

import static edu.tsinghua.lumaqq.resource.Messages.*;

import java.util.ArrayList;
import java.util.List;

import org.eclipse.jface.dialogs.IDialogConstants;
import org.eclipse.jface.dialogs.IInputValidator;
import org.eclipse.jface.dialogs.InputDialog;
import org.eclipse.jface.dialogs.MessageDialog;
import org.eclipse.jface.viewers.StructuredSelection;
import org.eclipse.osgi.util.NLS;
import org.eclipse.swt.SWT;
import org.eclipse.swt.graphics.Color;
import org.eclipse.swt.graphics.Point;
import org.eclipse.swt.graphics.RGB;
import org.eclipse.swt.widgets.ColorDialog;
import org.eclipse.swt.widgets.Display;
import org.eclipse.swt.widgets.MessageBox;
import org.eclipse.swt.widgets.Shell;

import edu.tsinghua.lumaqq.LumaQQ;
import edu.tsinghua.lumaqq.disk.DiskContentProvider;
import edu.tsinghua.lumaqq.ecore.global.Robot;
import edu.tsinghua.lumaqq.models.Cluster;
import edu.tsinghua.lumaqq.models.Dummy;
import edu.tsinghua.lumaqq.models.Group;
import edu.tsinghua.lumaqq.models.GroupType;
import edu.tsinghua.lumaqq.models.Model;
import edu.tsinghua.lumaqq.models.Organization;
import edu.tsinghua.lumaqq.models.User;
import edu.tsinghua.lumaqq.qq.QQ;
import edu.tsinghua.lumaqq.qq.QQClient;
import edu.tsinghua.lumaqq.qq.Util;
import edu.tsinghua.lumaqq.qq.beans.Directory;
import edu.tsinghua.lumaqq.qq.beans.File;
import edu.tsinghua.lumaqq.qq.beans.Member;
import edu.tsinghua.lumaqq.qq.beans.QQOrganization;
import edu.tsinghua.lumaqq.resource.Resources;
import edu.tsinghua.lumaqq.ui.MainShell;
import edu.tsinghua.lumaqq.ui.MemberEditShell;
import edu.tsinghua.lumaqq.ui.SMSWindow;
import edu.tsinghua.lumaqq.ui.config.sys.SystemOptionWindow;
import edu.tsinghua.lumaqq.ui.config.user.UserInfoWindow;
import edu.tsinghua.lumaqq.ui.debug.Debugger;
import edu.tsinghua.lumaqq.ui.dialogs.AboutDialog;
import edu.tsinghua.lumaqq.ui.dialogs.DiskShareDialog;
import edu.tsinghua.lumaqq.ui.jobs.CreateDirectoryJob;
import edu.tsinghua.lumaqq.ui.jobs.DeleteJob;
import edu.tsinghua.lumaqq.ui.jobs.DialogJobExecutor;
import edu.tsinghua.lumaqq.ui.jobs.DownloadFriendRemarkJob;
import edu.tsinghua.lumaqq.ui.jobs.DownloadGroupJob;
import edu.tsinghua.lumaqq.ui.jobs.IExecutor;
import edu.tsinghua.lumaqq.ui.jobs.RenameJob;
import edu.tsinghua.lumaqq.ui.jobs.UploadGroupJob;
import edu.tsinghua.lumaqq.ui.wizard.WizardWindow;
import edu.tsinghua.lumaqq.ui.wizard.search.SearchWizardModel;
import edu.tsinghua.lumaqq.widgets.menu.CMenu;
import edu.tsinghua.lumaqq.widgets.menu.CMenuItem;
import edu.tsinghua.lumaqq.widgets.menu.IMenuListener;
import edu.tsinghua.lumaqq.widgets.menu.ISelectionListener;
import edu.tsinghua.lumaqq.widgets.menu.MenuEvent;
import edu.tsinghua.lumaqq.widgets.menu.SelectionEvent;
import edu.tsinghua.lumaqq.widgets.qstyle.QTreeViewer;

/**
 * ????
 * 
 * @author luma
 */
public class MenuHelper {
    private MainShell main;
    private ShellLauncher shellLauncher;
    private Resources res;
    private ExportHelper exportHelper;
    private Shell shell;
    private QQClient client;
    private Display display;
    private OptionHelper options;
    private BlindHelper blindHelper;

    private CMenu statusMenu, sysMenu, groupMenu, friendMenu, awayMenu, displayMenu, clusterMenu;
    private CMenu organizationMenu, organizationContainerMenu, subjectMenu, memberMenu, dialogContainerMenu;
    private CMenu plusMenu;
    private CMenu diskMenu;

    private CMenu robotMenu;
    private boolean robotInitialized;

    public MenuHelper(MainShell main) {
        this.main = main;
        shellLauncher = main.getShellLauncher();
        res = Resources.getInstance();
        exportHelper = main.getExportHelper();
        shell = main.getShell();
        client = main.getClient();
        display = main.getDisplay();
        options = main.getOptionHelper();
        blindHelper = main.getBlindHelper();
        robotInitialized = false;
    }

    /**
     * ??
     */
    public void initMenu() {
        initStatusMenu();
        initSysMenu();
        initGroupMenu();
        initFriendMenu();
        initClusterMenu();
        initOrganizationContainerMenu();
        initSubjectMenu();
        initMemberMenu();
        initDialogContainerMenu();
        initOrganizationMenu();
        initPlusMenu();
        initDiskMenu();
    }

    /**
     * ???
     */
    private void initDiskMenu() {
        diskMenu = new CMenu();
        // 
        final CMenuItem miRefresh = new CMenuItem(diskMenu, SWT.PUSH);
        miRefresh.setImage(res.getImage(Resources.icoRefresh));
        miRefresh.setText(disk_tooltip_refresh);
        miRefresh.addSelectionListener(new ISelectionListener() {
            public void widgetSelected(SelectionEvent e) {
                Object obj = diskMenu.getData();
                main.getDiskManager().refresh(obj);
                main.getDiskViewer().refresh();
            }
        });
        // 
        final CMenuItem miShare = new CMenuItem(diskMenu, SWT.PUSH);
        miShare.setText(disk_tooltip_set_share);
        miShare.addSelectionListener(new ISelectionListener() {
            public void widgetSelected(SelectionEvent e) {
                Directory dir = (Directory) diskMenu.getData();
                DiskShareDialog dialog = new DiskShareDialog(main, dir);
                dialog.open();
            }
        });
        // separator
        new CMenuItem(diskMenu, SWT.SEPARATOR);
        // 
        final CMenuItem miUpload = new CMenuItem(diskMenu, SWT.PUSH);
        miUpload.setImage(res.getImage(Resources.icoDiskUpload));
        miUpload.setText(disk_tooltip_upload);
        miUpload.addSelectionListener(new ISelectionListener() {
            public void widgetSelected(SelectionEvent e) {
            }
        });
        // 
        final CMenuItem miDownload = new CMenuItem(diskMenu, SWT.PUSH);
        miDownload.setImage(res.getImage(Resources.icoDiskDownload));
        miDownload.setText(disk_tooltip_download);
        miDownload.addSelectionListener(new ISelectionListener() {
            public void widgetSelected(SelectionEvent e) {
                main.onDiskDownload(new StructuredSelection(diskMenu.getData()));
            }
        });
        // separator
        new CMenuItem(diskMenu, SWT.SEPARATOR);
        // 
        final CMenuItem miDelete = new CMenuItem(diskMenu, SWT.PUSH);
        miDelete.setText(disk_tooltip_delete);
        miDelete.addSelectionListener(new ISelectionListener() {
            public void widgetSelected(SelectionEvent e) {
                Object obj = diskMenu.getData();
                if (obj instanceof Directory) {
                    Directory dir = (Directory) obj;
                    if (dir.isSystemDir()) {
                        MessageDialog.openWarning(main.getShell(), message_box_common_warning_title,
                                disk_hint_cannot_delete_system_dir);
                        return;
                    }
                }
                String msg = null;
                if (obj instanceof Integer)
                    msg = NLS.bind(disk_hint_confirm_delete, String.valueOf(obj));
                else if (obj instanceof File)
                    msg = NLS.bind(disk_hint_confirm_delete, ((File) obj).name);
                else if (obj instanceof Directory)
                    msg = NLS.bind(disk_hint_confirm_delete, ((Directory) obj).name);
                else
                    return;

                if (MessageDialog.openQuestion(main.getShell(), message_box_common_question_title, msg)) {
                    if (obj instanceof Integer)
                        main.getDiskJobQueue().addJob(new DeleteJob((Integer) obj));
                    else if (obj instanceof File)
                        main.getDiskJobQueue().addJob(new DeleteJob((File) obj));
                    else
                        main.getDiskJobQueue().addJob(new DeleteJob((Directory) obj));
                }
            }
        });
        // separator
        new CMenuItem(diskMenu, SWT.SEPARATOR);
        // ???
        final CMenuItem miRename = new CMenuItem(diskMenu, SWT.PUSH);
        miRename.setText(disk_tooltip_rename);
        miRename.addSelectionListener(new ISelectionListener() {
            public void widgetSelected(SelectionEvent e) {
                Object obj = diskMenu.getData();
                boolean renameFile = obj instanceof File;
                InputDialog dialog = new InputDialog(main.getShell(), "Rename", disk_hint_input_new_name,
                        renameFile ? ((File) obj).name : ((Directory) obj).name, new IInputValidator() {
                            public String isValid(String newText) {
                                if (!newText.equals(""))
                                    return null;
                                else
                                    return disk_hint_name_cannot_null;
                            }
                        });
                if (dialog.open() == IDialogConstants.OK_ID) {
                    if (renameFile)
                        main.getDiskJobQueue().addJob(new RenameJob((File) obj, dialog.getValue()));
                    else
                        main.getDiskJobQueue().addJob(new RenameJob((Directory) obj, dialog.getValue()));
                }
            }
        });
        // 
        final CMenuItem miNewFolder = new CMenuItem(diskMenu, SWT.PUSH);
        miNewFolder.setText(disk_tooltip_new_directory);
        miNewFolder.addSelectionListener(new ISelectionListener() {
            public void widgetSelected(SelectionEvent e) {
                Object obj = diskMenu.getData();
                int parentId = (obj instanceof Integer) ? 0 : ((Directory) obj).id;
                InputDialog dialog = new InputDialog(main.getShell(), "New", disk_hint_input_new_name, null,
                        new IInputValidator() {
                            public String isValid(String newText) {
                                if (!newText.equals(""))
                                    return null;
                                else
                                    return disk_hint_name_cannot_null;
                            }
                        });
                if (dialog.open() == IDialogConstants.OK_ID) {
                    main.getDiskJobQueue().addJob(new CreateDirectoryJob(dialog.getValue(), parentId));
                }
            }
        });

        // ??
        diskMenu.addMenuListener(new IMenuListener() {
            public void menuShown(MenuEvent e) {
                Object obj = diskMenu.getData();
                if (obj == null) {
                    miRefresh.setEnabled(false);
                    miDownload.setEnabled(false);
                    miUpload.setEnabled(false);
                    miRename.setEnabled(false);
                    miDelete.setEnabled(false);
                    miShare.setEnabled(false);
                } else {
                    if (obj instanceof Integer)
                        miRefresh.setEnabled(true);
                    else if (obj instanceof Directory) {
                        Directory dir = (Directory) obj;
                        switch (dir.id) {
                        case QQ.QQ_DISK_DIR_MY_FAVORITE:
                        case QQ.QQ_DISK_DIR_MY_ALBUM:
                            miRefresh.setEnabled(true);
                            break;
                        default:
                            miRefresh.setEnabled(false);
                            break;
                        }
                    } else
                        miRefresh.setEnabled(false);

                    miDownload.setEnabled(obj instanceof File);
                    miShare.setEnabled(obj instanceof Directory && ((Directory) obj).owner == main.getMyModel().qq);
                    miUpload.setEnabled(
                            obj instanceof Directory && main.getDiskManager().isChildCreatable((Directory) obj)
                                    || obj instanceof Integer && (Integer) obj == DiskContentProvider.MY_DISK);
                    miRename.setEnabled(obj instanceof File && ((File) obj).owner == main.getMyModel().qq
                            || obj instanceof Directory && ((Directory) obj).owner == main.getMyModel().qq
                                    && !((Directory) obj).isSystemDir());
                    miDelete.setEnabled(obj instanceof File && ((File) obj).owner == main.getMyModel().qq
                            || obj instanceof Directory && ((Directory) obj).owner == main.getMyModel().qq
                            || obj instanceof Integer && (Integer) obj > 10000);
                    if (obj instanceof Directory) {
                        miNewFolder.setEnabled(main.getDiskManager().isChildCreatable((Directory) obj));
                    } else if (obj instanceof Integer) {
                        miNewFolder.setEnabled((Integer) obj == DiskContentProvider.MY_DISK);
                    } else
                        miNewFolder.setEnabled(false);
                }
            }
        });
    }

    /**
     * ??plus??
     */
    private void initPlusMenu() {
        plusMenu = new CMenu();
        plusMenu.setImageSize(20);
        // ?
        CMenuItem mi = new CMenuItem(plusMenu, SWT.PUSH);
        mi.setImage(res.getImage(Resources.icoFriendView));
        mi.setText(menu_plus_friend_view);
        mi.addSelectionListener(new ISelectionListener() {
            public void widgetSelected(SelectionEvent e) {
                main.switchView(MainShell.VIEW_FRIEND);
            }
        });
        // 
        mi = new CMenuItem(plusMenu, SWT.PUSH);
        mi.setImage(res.getImage(Resources.icoDiskView));
        mi.setText(menu_plus_disk);
        mi.addSelectionListener(new ISelectionListener() {
            public void widgetSelected(SelectionEvent e) {
                if (main.getClient().getUser().isLoggedIn()) {
                    main.switchView(MainShell.VIEW_DISK);
                }
            }
        });
    }

    /**
     * ???
     */
    private void initOrganizationMenu() {
        organizationMenu = new CMenu();
        // 
        CMenuItem mi = new CMenuItem(organizationMenu, SWT.PUSH);
        mi.setImage(res.getImage(Resources.icoRefresh));
        mi.setText(menu_organization_refresh);
        mi.addSelectionListener(new ISelectionListener() {

            public void widgetSelected(SelectionEvent e) {
                Organization org = (Organization) organizationMenu.getData();
                client.updateOrganization(org.cluster.clusterId);
            }
        });
        // ?
        mi = new CMenuItem(organizationMenu, SWT.PUSH);
        mi.setImage(res.getImage(Resources.icoDialog));
        mi.setText(menu_organization_discuss);
        mi.addSelectionListener(new ISelectionListener() {

            public void widgetSelected(SelectionEvent e) {
                Organization org = (Organization) organizationMenu.getData();
                List<Integer> members = new ArrayList<Integer>();
                int myQQ = main.getMyModel().qq;
                boolean hasMe = false;
                for (User u : org.cluster.members.values()) {
                    if (u.organizationId == org.id) {
                        members.add(u.qq);
                        if (u.qq == myQQ)
                            hasMe = true;
                    }
                }
                if (members.isEmpty() || members.size() == 1 && members.get(0) == myQQ) {
                    MessageDialog.openInformation(main.getShell(), message_box_common_info_title,
                            message_box_empty_organization);
                    return;
                } else if (members.size() == 2 && (members.get(0) == myQQ || members.get(1) == myQQ)) {
                    if (members.get(0) != myQQ)
                        shellLauncher.openIMShell(members.get(0));
                    else if (members.get(1) != myQQ)
                        shellLauncher.openIMShell(members.get(1));
                } else {
                    if (!hasMe)
                        members.add(myQQ);

                    // ??
                    Cluster subject = null;
                    boolean hasSubject = true;
                    for (Cluster c : org.cluster.subClusters.values()) {
                        if (c.name.equals(org.name) && c.members.size() == members.size()) {
                            for (Integer qq : members) {
                                if (!c.hasMember(qq)) {
                                    hasSubject = false;
                                    break;
                                }
                            }
                            if (hasSubject) {
                                subject = c;
                                break;
                            } else
                                hasSubject = true;
                        }
                    }
                    // ??
                    if (subject == null) {
                        main.getUIHelper().addPromotingDiscuss(main.getClient().createTemporaryCluster(org.name,
                                QQ.QQ_CLUSTER_TYPE_SUBJECT, org.cluster.clusterId, members));
                    } else {
                        shellLauncher.openClusterIMWindow(subject);
                    }
                }
            }
        });
        // separator
        new CMenuItem(organizationMenu, SWT.SEPARATOR);
        // 
        final CMenuItem miModify = new CMenuItem(organizationMenu, SWT.PUSH);
        miModify.setText(menu_organization_modify);
        miModify.addSelectionListener(new ISelectionListener() {

            public void widgetSelected(SelectionEvent e) {
                Organization org = (Organization) organizationMenu.getData();
                Organization parent = null;
                for (Organization o : org.cluster.organizations.values()) {
                    if (o.isParentOf(org)) {
                        parent = o;
                        break;
                    }
                }
                shellLauncher.openMemberEditShell(MemberEditShell.ORGANIZATION, org.cluster, parent, org);
            }
        });
        // 
        final CMenuItem miAdd = new CMenuItem(organizationMenu, SWT.PUSH);
        miAdd.setText(menu_organization_add);
        miAdd.addSelectionListener(new ISelectionListener() {

            public void widgetSelected(SelectionEvent e) {
                Organization org = (Organization) organizationMenu.getData();
                if (org.getLevel() >= 3) {
                    MessageDialog.openInformation(main.getShell(), message_box_common_info_title,
                            message_box_max_organization_level);
                    return;
                }
                // TODO ???
                shellLauncher.openMemberEditShell(MemberEditShell.ORGANIZATION, org.cluster, org, null);
            }
        });
        // 
        final CMenuItem miRemove = new CMenuItem(organizationMenu, SWT.PUSH);
        miRemove.setText(menu_organization_remove);
        miRemove.addSelectionListener(new ISelectionListener() {

            public void widgetSelected(SelectionEvent e) {
                Organization org = (Organization) organizationMenu.getData();
                Cluster cluster = org.cluster;
                // ???
                boolean hasChildren = false;
                for (Organization o : cluster.organizations.values()) {
                    if (o.isChildOf(org)) {
                        hasChildren = true;
                        break;
                    }
                }
                if (!hasChildren) {
                    for (User u : cluster.members.values()) {
                        if (u.organizationId == org.id) {
                            hasChildren = true;
                            break;
                        }
                    }
                }
                if (hasChildren) {
                    MessageDialog.openInformation(main.getShell(), message_box_common_info_title,
                            message_box_empty_organization_first);
                    return;
                }
                // ui
                Organization parentOrg = org.getParent();
                cluster.removeOrganization(org);

                // id?id?1
                int id = org.id + 1;
                while (cluster.hasOrganization(id)) {
                    cluster.decreaseOrganizationId(id);
                    id++;
                }
                // ?id
                List<Member> changedMember = new ArrayList<Member>();
                for (User u : cluster.members.values()) {
                    if (u.organizationId > org.id) {
                        u.organizationId--;
                        Member m = new Member();
                        m.qq = u.qq;
                        m.organization = u.organizationId;
                        changedMember.add(m);
                    }
                }
                // ???path
                // ?????
                if (parentOrg != null) {
                    Organization lastChild = org;
                    for (Organization o : cluster.organizations.values()) {
                        if (o.isChildOf(parentOrg)) {
                            if (o.getShiftMaskLevelId() > lastChild.getShiftMaskLevelId())
                                lastChild = o;
                        }
                    }

                    // ???path
                    if (lastChild != org) {
                        int level = lastChild.getLevel();
                        int newValue = org.getShiftMaskLevelId();
                        for (Organization o : cluster.organizations.values()) {
                            if (lastChild.isPrefixOf(o))
                                o.setLevelId(level, newValue);
                        }
                        lastChild.setLevelId(newValue);
                    }
                }

                // ???
                List<QQOrganization> temp = new ArrayList<QQOrganization>();
                for (Organization o : cluster.organizations.values()) {
                    QQOrganization qqOrg = new QQOrganization();
                    qqOrg.id = o.id;
                    qqOrg.path = o.path;
                    qqOrg.name = o.name;
                    temp.add(qqOrg);
                }
                main.getClient().commitOrganization(cluster.clusterId, temp);
                main.getClient().commitMemberOrganization(cluster.clusterId, changedMember);
                main.getBlindHelper().refreshGroup(cluster.group);
            }
        });

        // ???
        organizationMenu.addMenuListener(new IMenuListener() {
            public void menuShown(MenuEvent e) {
                Organization org = (Organization) organizationMenu.getData();
                boolean admin = org.cluster.isSuperMember(main.getMyModel().qq);
                miModify.setEnabled(admin);
                miAdd.setEnabled(admin);
                miRemove.setEnabled(admin);
            }
        });
    }

    /**
     * ????
     */
    private void initDialogContainerMenu() {
        dialogContainerMenu = new CMenu();
        // ?
        CMenuItem mi = new CMenuItem(dialogContainerMenu, SWT.PUSH);
        mi.setImage(res.getImage(Resources.icoDialog));
        mi.setText(menu_dialog_new);
        mi.addSelectionListener(new ISelectionListener() {
            public void widgetSelected(SelectionEvent e) {
                shellLauncher.openMemberEditShell(MemberEditShell.TEMP_CLUSTER, null, null, null);
            }
        });
        // 
        mi = new CMenuItem(dialogContainerMenu, SWT.PUSH);
        mi.setImage(res.getImage(Resources.icoRefresh));
        mi.setText(menu_dialog_refresh);
        mi.addSelectionListener(new ISelectionListener() {
            public void widgetSelected(SelectionEvent e) {
                client.getDialogList();
            }
        });
    }

    /**
     * ????
     */
    private void initMemberMenu() {
        memberMenu = new CMenu();
        // ??
        final CMenuItem miSend = new CMenuItem(memberMenu, SWT.PUSH);
        miSend.setImage(res.getImage(Resources.icoSendReceiveMessage));
        miSend.setText(menu_friend_sendreceive);
        miSend.addSelectionListener(new ISelectionListener() {
            public void widgetSelected(SelectionEvent e) {
                User u = (User) memberMenu.getData();
                shellLauncher.openNormalIMWindow(u);
            }
        });
        // ?
        CMenuItem mi = new CMenuItem(memberMenu, SWT.PUSH);
        mi.setImage(res.getImage(Resources.icoTempSessionIM));
        mi.setText(menu_friend_temp_session);
        mi.addSelectionListener(new ISelectionListener() {
            public void widgetSelected(SelectionEvent e) {
                User u = (User) memberMenu.getData();
                shellLauncher.openTempSessionIMWindow(u.qq);
            }
        });
        // ?
        final CMenuItem miAdd = new CMenuItem(memberMenu, SWT.PUSH);
        miAdd.setImage(res.getImage(Resources.icoAddFriend));
        miAdd.setText(cluster_im_menu_member_add);
        miAdd.addSelectionListener(new ISelectionListener() {
            public void widgetSelected(SelectionEvent e) {
                User u = (User) memberMenu.getData();
                shellLauncher.openAddReceiveSystemMessageShell(u);
                client.addFriend(u.qq);
            }
        });
        // 
        mi = new CMenuItem(memberMenu, SWT.PUSH);
        mi.setImage(res.getImage(Resources.icoPersonInfo));
        mi.setText(menu_friend_viewinfo);
        mi.addSelectionListener(new ISelectionListener() {
            public void widgetSelected(SelectionEvent e) {
                User u = (User) memberMenu.getData();
                if (u.qq == main.getMyModel().qq)
                    u.info = main.getMyModel().info;
                UserInfoWindow uiw = shellLauncher.openUserInfoWindow(u,
                        (u.qq == main.getMyModel().qq) ? UserInfoWindow.EDITABLE : UserInfoWindow.READ_ONLY);
                uiw.setCurrentPage(UserInfoWindow.CARD);
            }
        });
        // separator
        new CMenuItem(memberMenu, SWT.SEPARATOR);
        // ??
        mi = new CMenuItem(memberMenu, SWT.PUSH);
        mi.setImage(res.getImage(Resources.icoRename));
        mi.setText(menu_friend_rename);
        mi.addSelectionListener(new ISelectionListener() {
            public void widgetSelected(SelectionEvent e) {
                User f = (User) memberMenu.getData();
                blindHelper.getViewer(f).editText(f);
            }
        });
        // 
        final CMenuItem miPin = new CMenuItem(memberMenu, SWT.PUSH);
        miPin.setImage(res.getImage(Resources.icoPin));
        miPin.setText(menu_friend_pin);
        miPin.addSelectionListener(new ISelectionListener() {
            public void widgetSelected(SelectionEvent e) {
                User f = (User) memberMenu.getData();
                f.pinned = !f.pinned;
                blindHelper.refreshGroup(f.group);
            }
        });

        // add menu listener
        memberMenu.addMenuListener(new IMenuListener() {
            public void menuShown(MenuEvent e) {
                User u = (User) memberMenu.getData();
                boolean friend = u.isFriend();
                miSend.setEnabled(friend);
                miAdd.setEnabled(!friend);
                miPin.setText(u.pinned ? menu_friend_unpin : menu_friend_pin);
            }
        });
    }

    /**
     * ???
     */
    private void initSubjectMenu() {
        subjectMenu = new CMenu();
        // 
        CMenuItem mi = new CMenuItem(subjectMenu, SWT.PUSH);
        mi.setImage(res.getImage(Resources.icoNewSubject));
        mi.setText(menu_subject_new);
        mi.addSelectionListener(new ISelectionListener() {

            public void widgetSelected(SelectionEvent e) {
                Dummy dummy = (Dummy) subjectMenu.getData();
                shellLauncher.openMemberEditShell(MemberEditShell.TEMP_CLUSTER, dummy.cluster, null, null);
            }
        });
        // 
        mi = new CMenuItem(subjectMenu, SWT.PUSH);
        mi.setImage(res.getImage(Resources.icoRefresh));
        mi.setText(menu_subject_refresh_all);
        mi.addSelectionListener(new ISelectionListener() {

            public void widgetSelected(SelectionEvent e) {
                Dummy dummy = (Dummy) subjectMenu.getData();
                client.getSubjectList(dummy.cluster.clusterId);
            }
        });
    }

    /**
     * ???
     */
    private void initOrganizationContainerMenu() {
        organizationContainerMenu = new CMenu();
        // 
        CMenuItem mi = new CMenuItem(organizationContainerMenu, SWT.PUSH);
        mi.setImage(res.getImage(Resources.icoRefresh));
        mi.setText(menu_organization_refresh);
        mi.addSelectionListener(new ISelectionListener() {

            public void widgetSelected(SelectionEvent e) {
                Dummy dummy = (Dummy) organizationContainerMenu.getData();
                client.updateOrganization(dummy.cluster.clusterId);
            }
        });
        // 
        final CMenuItem miAdd = new CMenuItem(organizationContainerMenu, SWT.PUSH);
        miAdd.setImage(res.getImage(Resources.icoOrganization));
        miAdd.setText(menu_organization_add);
        miAdd.addSelectionListener(new ISelectionListener() {

            public void widgetSelected(SelectionEvent e) {
                Dummy dummy = (Dummy) organizationContainerMenu.getData();
                // TODO ???
                shellLauncher.openMemberEditShell(MemberEditShell.ORGANIZATION, dummy.cluster, null, null);
            }
        });

        // ???
        organizationContainerMenu.addMenuListener(new IMenuListener() {

            public void menuShown(MenuEvent e) {
                Dummy dummy = (Dummy) organizationContainerMenu.getData();
                miAdd.setEnabled(dummy.cluster.isSuperMember(main.getMyModel().qq));
            }
        });
    }

    /**
     * ???
     */
    private void initClusterMenu() {
        clusterMenu = new CMenu();
        // ??
        CMenuItem mi = new CMenuItem(clusterMenu, SWT.PUSH);
        mi.setText(menu_cluster_send);
        mi.setImage(res.getImage(Resources.icoSendReceiveMessage));
        mi.addSelectionListener(new ISelectionListener() {
            public void widgetSelected(SelectionEvent e) {
                shellLauncher.openClusterIMWindow((Cluster) clusterMenu.getData());
            }
        });
        // 
        final CMenuItem miInfo = new CMenuItem(clusterMenu, SWT.PUSH);
        miInfo.setImage(res.getImage(Resources.icoClusterInfo));
        miInfo.addSelectionListener(new ISelectionListener() {
            public void widgetSelected(SelectionEvent e) {
                // model
                Cluster c = (Cluster) clusterMenu.getData();
                if (c.isPermanent())
                    shellLauncher.openClusterInfoWindow(c);
                else
                    shellLauncher.openMemberEditShell(MemberEditShell.TEMP_CLUSTER, c.getParentCluster(), null, c);
            }
        });
        // separator
        mi = new CMenuItem(clusterMenu, SWT.SEPARATOR);
        // ????
        mi = new CMenuItem(clusterMenu, SWT.CASCADE);
        mi.setText(menu_cluster_message_manage);
        mi.setImage(res.getImage(Resources.icoMessageManage));
        CMenu msgMenu = new CMenu(mi);
        // ??
        mi = new CMenuItem(msgMenu, SWT.PUSH);
        mi.setText(menu_cluster_message_export);
        mi.setImage(res.getImage(Resources.icoTxtFile));
        mi.addSelectionListener(new ISelectionListener() {
            public void widgetSelected(SelectionEvent e) {
                // model
                Cluster c = (Cluster) clusterMenu.getData();
                // 
                exportHelper.exportMessage(c);
            }
        });
        // separator
        mi = new CMenuItem(clusterMenu, SWT.SEPARATOR);
        // 
        mi = new CMenuItem(clusterMenu, SWT.PUSH);
        mi.setText(menu_cluster_exit);
        mi.setImage(res.getImage(Resources.icoExit));
        mi.addSelectionListener(new ISelectionListener() {
            public void widgetSelected(SelectionEvent e) {
                Cluster c = (Cluster) clusterMenu.getData();
                boolean yes = false;
                if (c.creator == main.getMyModel().qq)
                    yes = MessageDialog.openQuestion(shell, message_box_common_question_title,
                            message_box_exit_my_cluster);
                else
                    yes = MessageDialog.openQuestion(shell, message_box_common_question_title,
                            message_box_exit_cluster);
                if (yes) {
                    if (c.isPermanent()) {
                        if (c.creator == main.getMyModel().qq)
                            client.dismissCluster(c.clusterId);
                        else
                            client.exitCluster(c.clusterId);
                    } else
                        client.exitTempCluster(c.clusterType.toQQConstant(), c.clusterId, c.parentClusterId);
                }
            }
        });
        // ???
        clusterMenu.addMenuListener(new IMenuListener() {
            public void menuShown(MenuEvent e) {
                // model
                Cluster c = (Cluster) clusterMenu.getData();

                if (!c.isPermanent() || c.isSuperMember(main.getMyModel().qq))
                    miInfo.setText(menu_cluster_modifyinfo);
                else
                    miInfo.setText(menu_cluster_viewinfo);
            }
        });
    }

    /**
     * ???
     */
    private void initGroupMenu() {
        groupMenu = new CMenu();
        // /??
        final CMenuItem miHeadSize = new CMenuItem(groupMenu, SWT.PUSH);
        miHeadSize.addSelectionListener(new ISelectionListener() {
            public void widgetSelected(SelectionEvent e) {
                boolean b = options.isShowSmallHead();
                blindHelper.setShowSmallHead(!b);
                options.setShowSmallHead(!b);
            }
        });
        // ???
        final CMenuItem miCluster = new CMenuItem(groupMenu, SWT.CASCADE);
        miCluster.setText(menu_group_cluster);
        miCluster.setImage(res.getImage(Resources.icoCluster));
        CMenu subMenu = new CMenu(miCluster);
        // 
        CMenuItem mi = new CMenuItem(subMenu, SWT.PUSH);
        mi.setText(menu_group_cluster_search);
        mi.setImage(res.getImage(Resources.icoSearchCluster));
        mi.addSelectionListener(new ISelectionListener() {
            public void widgetSelected(SelectionEvent e) {
                if (main.getClient().getUser().isLoggedIn()) {
                    WizardWindow window = shellLauncher.openSearchWizard();
                    SearchWizardModel model = (SearchWizardModel) window.getModel();
                    model.setSearchWhat(SearchWizardModel.CLUSTER);
                    model.setStartingPage(SearchWizardModel.PAGE_HOW_TO_SEARCH_CLUSTER);
                    window.showStartingPage();
                }
            }
        });
        // 
        mi = new CMenuItem(subMenu, SWT.PUSH);
        mi.setText(menu_group_cluster_create);
        mi.setImage(res.getImage(Resources.icoAddCluster));
        mi.addSelectionListener(new ISelectionListener() {
            public void widgetSelected(SelectionEvent e) {
                shellLauncher.openClusterWizard();
            }
        });
        // ?
        mi = new CMenuItem(subMenu, SWT.PUSH);
        mi.setText(menu_group_alumni_search);
        mi.setImage(res.getImage(Resources.icoSearchCluster));
        mi.addSelectionListener(new ISelectionListener() {
            public void widgetSelected(SelectionEvent e) {
                shellLauncher.goAlumni();
            }
        });
        // ?
        mi = new CMenuItem(subMenu, SWT.PUSH);
        mi.setText(menu_group_alumni_create);
        mi.setImage(res.getImage(Resources.icoAddAlbum));
        mi.addSelectionListener(new ISelectionListener() {
            public void widgetSelected(SelectionEvent e) {
                shellLauncher.goAlumni();
            }
        });
        // separator
        mi = new CMenuItem(subMenu, SWT.SEPARATOR);
        // 
        mi = new CMenuItem(subMenu, SWT.PUSH);
        mi.setText(menu_group_community);
        mi.setImage(res.getImage(Resources.icoCluster));
        mi.addSelectionListener(new ISelectionListener() {
            public void widgetSelected(SelectionEvent e) {
                shellLauncher.goClusterCommunity();
            }
        });
        // 
        mi = new CMenuItem(groupMenu, SWT.CASCADE);
        mi.setText(menu_group_color);
        mi.setImage(res.getImage(Resources.icoColor));
        // 
        CMenu colorMenu = new CMenu(mi);
        CMenuItem sub = new CMenuItem(colorMenu, SWT.PUSH);
        sub.setText(menu_group_group_color);
        sub.addSelectionListener(new ISelectionListener() {
            public void widgetSelected(SelectionEvent e) {
                // ?
                ColorDialog dialog = new ColorDialog(shell);
                // ?
                RGB oldRGB = options.getGroupBackgroup();
                dialog.setRGB(oldRGB);
                // ??null
                RGB rgb = dialog.open();
                if (rgb != null) {
                    options.setGroupBackgroup(rgb);
                    if (main.getGroupColor() != null)
                        main.getGroupColor().dispose();
                    main.setGroupColor(new Color(display, rgb));
                }
            }
        });
        // ??
        final CMenuItem miName = new CMenuItem(groupMenu, SWT.CASCADE);
        miName.setText(menu_group_displayname);
        // 
        displayMenu = new CMenu(miName);
        final CMenuItem miShowNick = new CMenuItem(displayMenu, SWT.RADIO);
        miShowNick.setText(menu_group_displayname_nick);
        miShowNick.addSelectionListener(new ISelectionListener() {
            public void widgetSelected(SelectionEvent e) {
                if (miShowNick.isSelected()) {
                    blindHelper.setShowNick(true);
                    blindHelper.refreshAll();
                    options.setShowNick(true);
                }
            }
        });
        // ??
        final CMenuItem miShowRemark = new CMenuItem(displayMenu, SWT.RADIO);
        miShowRemark.setText(menu_group_displayname_remark);
        miShowRemark.addSelectionListener(new ISelectionListener() {
            public void widgetSelected(SelectionEvent e) {
                if (miShowRemark.isSelected()) {
                    blindHelper.setShowNick(false);
                    blindHelper.refreshAll();
                    options.setShowNick(false);
                }
            }
        });
        // /???
        final CMenuItem miSwitchFriendTip = new CMenuItem(groupMenu, SWT.PUSH);
        miSwitchFriendTip.addSelectionListener(new ISelectionListener() {
            public void widgetSelected(SelectionEvent e) {
                main.getOptionHelper().setShowFrientTip(!main.getOptionHelper().isShowFriendTip());
            }
        });
        // Blind??
        final CMenuItem miSwitchMode = new CMenuItem(groupMenu, SWT.PUSH);
        miSwitchMode.addSelectionListener(new ISelectionListener() {
            public void widgetSelected(SelectionEvent e) {
                main.getMessageQueue().setPostpone(true);
                blindHelper.stopAllEffectOnBlind();
                boolean b = options.isTreeMode();
                options.setTreeModel(!b);
                blindHelper.setTreeMode(!b);
                blindHelper.resetAllImageEffect();
                main.getMessageQueue().setPostpone(false);
                main.getMessageHelper().processPostponedIM();
            }
        });
        // separator
        mi = new CMenuItem(groupMenu, SWT.SEPARATOR);
        // 
        mi = new CMenuItem(groupMenu, SWT.PUSH);
        mi.setText(menu_friend_addgroup);
        mi.addSelectionListener(new ISelectionListener() {
            public void widgetSelected(SelectionEvent e) {
                blindHelper.addGroup();

                // ??LumaQQ??????
                //main.getMVCHelper().updateGroupInServer();
            }
        });
        // 
        mi = new CMenuItem(groupMenu, SWT.PUSH);
        mi.setText(menu_group_addfriend);
        mi.setImage(res.getImage(Resources.icoAddFriend));
        mi.addSelectionListener(new ISelectionListener() {
            public void widgetSelected(SelectionEvent e) {
                shellLauncher.openSearchWizard();
            }
        });
        // separator
        mi = new CMenuItem(groupMenu, SWT.SEPARATOR);
        // ??
        final CMenuItem miShowOnlineOnly = new CMenuItem(groupMenu, SWT.PUSH);
        miShowOnlineOnly.addSelectionListener(new ISelectionListener() {
            public void widgetSelected(SelectionEvent e) {
                boolean b = options.isShowOnlineOnly();
                blindHelper.setShowOnlineOnly(!b);
                options.setShowOnlineOnly(!b);
                blindHelper.refreshAll();
            }
        });
        // ????
        // separator
        mi = new CMenuItem(groupMenu, SWT.SEPARATOR);
        // ???
        final CMenuItem miRename = new CMenuItem(groupMenu, SWT.PUSH);
        miRename.setText(menu_group_rename);
        miRename.setImage(res.getImage(Resources.icoRename));
        miRename.addSelectionListener(new ISelectionListener() {
            public void widgetSelected(SelectionEvent e) {
                if (blindHelper.isTreeMode()) {
                    QTreeViewer<Model> viewer = blindHelper.getCurrentViewer();
                    if (viewer == null)
                        return;
                    Group g = (Group) groupMenu.getData();
                    viewer.editText(g);
                } else
                    blindHelper.editCurrentSlatText();
            }
        });
        // 
        final CMenuItem miDelete = new CMenuItem(groupMenu, SWT.PUSH);
        miDelete.setText(menu_group_delete);
        miDelete.setImage(res.getImage(Resources.icoDelGroup));
        miDelete.addSelectionListener(new ISelectionListener() {
            public void widgetSelected(SelectionEvent e) {
                Group g = (Group) groupMenu.getData();
                if (g.users.size() > 0) {
                    MessageBox box = new MessageBox(shell, SWT.ICON_WARNING | SWT.OK);
                    box.setText(message_box_common_warning_title);
                    box.setMessage(hint_please_clear_friend);
                    box.open();
                } else {
                    blindHelper.removeGroup(g);

                    // ??LumaQQ??????
                    //main.getMVCHelper().updateGroupInServer();
                }
            }
        });
        // ??????????????
        // separator
        mi = new CMenuItem(groupMenu, SWT.SEPARATOR);
        // ?????
        final CMenuItem miAddBadGuy = new CMenuItem(groupMenu, SWT.PUSH);
        miAddBadGuy.setText(menu_group_addbadguy);
        miAddBadGuy.setImage(res.getImage(Resources.icoAddFriend));
        miAddBadGuy.addSelectionListener(new ISelectionListener() {
            public void widgetSelected(SelectionEvent e) {
                User f = new User();
                f.qq = 0;
                f.nick = "Input His QQ";
                f.displayName = f.nick;
                blindHelper.addUser(f, GroupType.BLACKLIST_GROUP);
                QTreeViewer<Model> viewer = blindHelper.getViewer(f);
                blindHelper.refreshGroup(f.group);
                blindHelper.expandGroup(f.group);
                viewer.editText(f);
            }
        });
        // ?????
        final CMenuItem miSwitchBlacklist = new CMenuItem(groupMenu, SWT.PUSH);
        miSwitchBlacklist.addSelectionListener(new ISelectionListener() {
            public void widgetSelected(SelectionEvent e) {
                boolean b = options.isShowBlacklist();
                options.setShowBlacklist(!b);
                blindHelper.setBlacklistGroupVisible(!b);
            }
        });

        // ???
        groupMenu.addMenuListener(new IMenuListener() {
            public void menuShown(MenuEvent e) {
                // ????
                if (options.isShowSmallHead()) {
                    miHeadSize.setText(menu_friend_showlarge);
                    miHeadSize.setImage(res.getImage(Resources.icoLargeHead));
                } else {
                    miHeadSize.setText(menu_friend_showsmall);
                    miHeadSize.setImage(res.getImage(Resources.icoSmallHead));
                }
                // ???
                if (options.isTreeMode()) {
                    miSwitchMode.setText(menu_group_traditional_mode);
                    miSwitchMode.setImage(res.getImage(Resources.icoTraditionalMode));
                } else {
                    miSwitchMode.setText(menu_group_tree_mode);
                    miSwitchMode.setImage(res.getImage(Resources.icoTreeMode));
                }
                // ?model
                Group g = (Group) groupMenu.getData();
                // ???????
                // ?
                if (options.isShowNick()) {
                    miShowNick.setSelected(true);
                    miShowRemark.setSelected(false);
                } else {
                    miShowNick.setSelected(false);
                    miShowRemark.setSelected(true);
                }
                // ???
                miCluster.setEnabled(g.isCluster());
                // ????
                if (main.getOptionHelper().isShowFriendTip()) {
                    miSwitchFriendTip.setImage(res.getImage(Resources.icoDisableFriendTip));
                    miSwitchFriendTip.setText(menu_group_disable_user_tip);
                } else {
                    miSwitchFriendTip.setImage(res.getImage(Resources.icoEnableFriendTip));
                    miSwitchFriendTip.setText(menu_group_enable_user_tip);
                }
                // ???
                miShowOnlineOnly
                        .setText(options.isShowOnlineOnly() ? menu_group_showall : menu_group_showonlineonly);
                // ????            
                if (g.isFriendly() && !g.isDefaultFriend()) {
                    miRename.setEnabled(true);
                    miDelete.setEnabled(true);
                } else {
                    miRename.setEnabled(false);
                    miDelete.setEnabled(false);
                }
                // ????
                miAddBadGuy.setEnabled(g.isBlackList());
                // ?????
                if (options.isShowBlacklist()) {
                    miSwitchBlacklist.setText(menu_group_hideblacklist);
                    miSwitchBlacklist.setImage(res.getImage(Resources.icoHideBlackList));
                } else {
                    miSwitchBlacklist.setText(menu_group_showblacklist);
                    miSwitchBlacklist.setImage(res.getImage(Resources.icoShowBlackList));
                }
            }
        });
    }

    /**
     * ?????
     */
    private void initFriendMenu() {
        friendMenu = new CMenu();
        // ??
        CMenuItem mi = new CMenuItem(friendMenu, SWT.PUSH);
        mi.setText(menu_friend_sendreceive);
        mi.setImage(res.getImage(Resources.icoSendReceiveMessage));
        mi.addSelectionListener(new ISelectionListener() {
            public void widgetSelected(SelectionEvent e) {
                // ?view part??
                shellLauncher.openNormalIMWindow((User) friendMenu.getData());
            }
        });
        // ??
        mi = new CMenuItem(friendMenu, SWT.PUSH);
        mi.setText(menu_friend_sendsms);
        mi.setImage(res.getImage(Resources.icoMobile));
        mi.addSelectionListener(new ISelectionListener() {
            public void widgetSelected(SelectionEvent e) {
                User f = (User) friendMenu.getData();
                SMSWindow window = shellLauncher.openSMSWindow(f);
                window.setReceiver(String.valueOf(f.qq));
            }
        });
        // ?
        mi = new CMenuItem(friendMenu, SWT.PUSH);
        mi.setImage(res.getImage(Resources.icoTempSessionIM));
        mi.setText(menu_friend_temp_session);
        mi.addSelectionListener(new ISelectionListener() {
            public void widgetSelected(SelectionEvent e) {
                User u = (User) friendMenu.getData();
                shellLauncher.openTempSessionIMWindow(u.qq);
            }
        });
        // separator
        mi = new CMenuItem(friendMenu, SWT.SEPARATOR);
        // 
        mi = new CMenuItem(friendMenu, SWT.PUSH);
        mi.setText(menu_friend_viewinfo);
        mi.setImage(res.getImage(Resources.icoPersonInfo));
        mi.addSelectionListener(new ISelectionListener() {
            public void widgetSelected(SelectionEvent e) {
                // ?view part?
                shellLauncher.openUserInfoWindow((User) friendMenu.getData(), UserInfoWindow.READ_ONLY);
            }
        });
        // ????
        mi = new CMenuItem(friendMenu, SWT.CASCADE);
        mi.setText(menu_friend_message_manage);
        mi.setImage(res.getImage(Resources.icoMessageManage));
        CMenu msgMenu = new CMenu(mi);
        // ??
        mi = new CMenuItem(msgMenu, SWT.PUSH);
        mi.setText(menu_friend_message_export);
        mi.setImage(res.getImage(Resources.icoTxtFile));
        mi.addSelectionListener(new ISelectionListener() {
            public void widgetSelected(SelectionEvent e) {
                // ?model
                User f = (User) friendMenu.getData();
                // 
                exportHelper.exportMessage(f);
            }
        });
        // separator
        mi = new CMenuItem(friendMenu, SWT.SEPARATOR);
        // /??
        final CMenuItem miSwitchHead = new CMenuItem(friendMenu, SWT.PUSH);
        miSwitchHead.setText(menu_friend_showsmall);
        miSwitchHead.setImage(res.getImage(Resources.icoSmallHead));
        miSwitchHead.addSelectionListener(new ISelectionListener() {
            public void widgetSelected(SelectionEvent e) {
                boolean b = options.isShowSmallHead();
                blindHelper.setShowSmallHead(!b);
                options.setShowSmallHead(!b);
            }
        });
        // 
        mi = new CMenuItem(friendMenu, SWT.PUSH);
        mi.setText(menu_friend_addgroup);
        mi.addSelectionListener(new ISelectionListener() {
            public void widgetSelected(SelectionEvent e) {
                blindHelper.addGroup();
            }
        });
        // separator
        mi = new CMenuItem(friendMenu, SWT.SEPARATOR);
        // ??
        final CMenuItem miShowOnlineOnly = new CMenuItem(friendMenu, SWT.PUSH);
        miShowOnlineOnly.addSelectionListener(new ISelectionListener() {
            public void widgetSelected(SelectionEvent e) {
                boolean b = options.isShowOnlineOnly();
                blindHelper.setShowOnlineOnly(!b);
                options.setShowOnlineOnly(!b);
                blindHelper.refreshAll();
            }
        });
        // separator
        mi = new CMenuItem(friendMenu, SWT.SEPARATOR);
        // 
        mi = new CMenuItem(friendMenu, SWT.PUSH);
        mi.setText(menu_friend_delfriend);
        mi.setImage(res.getImage(Resources.icoDelFriend));
        mi.addSelectionListener(new ISelectionListener() {
            public void widgetSelected(SelectionEvent e) {
                User f = (User) friendMenu.getData();
                // ???????
                // ??
                if (!f.isInFriendGroup()) {
                    blindHelper.simpleMove(f, f.group, null);
                } else {
                    MessageBox box = new MessageBox(shell, SWT.ICON_QUESTION | SWT.YES | SWT.NO);
                    box.setText(message_box_common_question_title);
                    box.setMessage(NLS.bind(hint_delete_friend, f.displayName));
                    if (box.open() == SWT.YES) {
                        shellLauncher.openDeleteReceiveSystemMessageShell(f);
                        main.deleteFriend(f, false, false);
                    }
                }
            }
        });
        // ??
        final CMenuItem miRename = new CMenuItem(friendMenu, SWT.PUSH);
        miRename.setText(menu_friend_rename);
        miRename.setImage(res.getImage(Resources.icoRename));
        miRename.addSelectionListener(new ISelectionListener() {
            public void widgetSelected(SelectionEvent e) {
                User f = (User) friendMenu.getData();
                blindHelper.getViewer(f).editText(f);
            }
        });
        // 
        final CMenuItem miPin = new CMenuItem(friendMenu, SWT.PUSH);
        miPin.setImage(res.getImage(Resources.icoPin));
        miPin.addSelectionListener(new ISelectionListener() {

            public void widgetSelected(SelectionEvent e) {
                User f = (User) friendMenu.getData();
                f.pinned = !f.pinned;
                blindHelper.refreshGroup(f.group);
            }
        });
        // ????????disable
        friendMenu.addMenuListener(new IMenuListener() {
            public void menuShown(MenuEvent e) {
                // ???
                if (options.isShowSmallHead()) {
                    miSwitchHead.setText(menu_friend_showlarge);
                    miSwitchHead.setImage(res.getImage(Resources.icoLargeHead));
                } else {
                    miSwitchHead.setText(menu_friend_showsmall);
                    miSwitchHead.setImage(res.getImage(Resources.icoSmallHead));
                }
                // 
                if (options.isShowOnlineOnly())
                    miShowOnlineOnly.setText(menu_friend_showall);
                else
                    miShowOnlineOnly.setText(menu_friend_showonlineonly);
                // ??
                User f = (User) friendMenu.getData();
                miRename.setEnabled(!f.group.isBlackList());
                // 
                miPin.setText(f.pinned ? menu_friend_unpin : menu_friend_pin);
            }
        });
    }

    /**
     * ???
     */
    private void initSysMenu() {
        // ??
        sysMenu = new CMenu();
        // ???
        final CMenuItem miGroupManage = new CMenuItem(sysMenu, SWT.CASCADE);
        miGroupManage.setText(menu_sys_group);
        miGroupManage.setImage(res.getImage(Resources.icoGroup));
        CMenu groupManageMenu = new CMenu(miGroupManage);
        // 
        CMenuItem sub = new CMenuItem(groupManageMenu, SWT.PUSH);
        sub.setText(menu_sys_group_upload);
        sub.setImage(res.getImage(Resources.icoUploadGroup));
        sub.addSelectionListener(new ISelectionListener() {
            public void widgetSelected(SelectionEvent e) {
                // ??
                if (!client.getUser().isLoggedIn())
                    return;
                IExecutor executor = new DialogJobExecutor(main);
                executor.addJob(new UploadGroupJob());
                executor.execute();
            }
        });
        // 
        sub = new CMenuItem(groupManageMenu, SWT.PUSH);
        sub.setText(menu_sys_group_download);
        sub.setImage(res.getImage(Resources.icoDownloadGroup));
        sub.addSelectionListener(new ISelectionListener() {
            public void widgetSelected(SelectionEvent e) {
                if (client.getUser().isLoggedIn()) {
                    main.getMessageQueue().setPostpone(true);
                    blindHelper.stopAllEffectOnBlind();
                    IExecutor executor = new DialogJobExecutor(main);
                    executor.addJob(new DownloadGroupJob());
                    executor.execute();
                    blindHelper.resetAllImageEffect();
                    main.getMessageQueue().setPostpone(false);
                    main.getMessageHelper().processPostponedIM();
                }
            }
        });
        // ?
        final CMenuItem miFriend = new CMenuItem(sysMenu, SWT.CASCADE);
        miFriend.setText(menu_sys_friend);
        miFriend.setImage(res.getImage(Resources.icoFriendInfoManage));
        CMenu infoMenu = new CMenu(miFriend);
        // ??
        CMenuItem mi = new CMenuItem(infoMenu, SWT.PUSH);
        mi.setText(menu_sys_friend_download_remark);
        mi.setImage(res.getImage(Resources.icoDownloadRemark));
        mi.addSelectionListener(new ISelectionListener() {
            public void widgetSelected(SelectionEvent e) {
                // ??
                if (!client.getUser().isLoggedIn())
                    return;
                DialogJobExecutor executor = new DialogJobExecutor(main);
                executor.setModeless(true);
                executor.setCancelable(true);
                executor.addJob(new DownloadFriendRemarkJob());
                executor.execute();
            }
        });
        // ??
        mi = new CMenuItem(infoMenu, SWT.PUSH);
        mi.setText(menu_sys_info_window);
        mi.setImage(res.getImage(Resources.icoMessageManage));
        mi.addSelectionListener(new ISelectionListener() {
            public void widgetSelected(SelectionEvent e) {
                shellLauncher.openInfoManagerWindow();
            }
        });
        // ?
        mi = new CMenuItem(infoMenu, SWT.PUSH);
        mi.setText(menu_sys_friend_export_record);
        mi.setImage(res.getImage(Resources.icoTxtFile));
        mi.addSelectionListener(new ISelectionListener() {
            public void widgetSelected(SelectionEvent e) {
                exportHelper.exportAllMessage();
            }
        });
        // 
        final CMenuItem miTool = new CMenuItem(sysMenu, SWT.CASCADE);
        miTool.setText(menu_sys_tool);
        miTool.setImage(res.getImage(Resources.icoTool));
        CMenu toolMenu = new CMenu(miTool);
        // QQ??
        mi = new CMenuItem(toolMenu, SWT.PUSH);
        mi.setText(menu_sys_apply);
        mi.setImage(res.getImage(Resources.icoApply));
        mi.addSelectionListener(new ISelectionListener() {
            public void widgetSelected(SelectionEvent e) {
                shellLauncher.goApply();
            }
        });
        // IP
        mi = new CMenuItem(toolMenu, SWT.PUSH);
        mi.setText(menu_sys_searchip);
        mi.setImage(res.getImage(Resources.icoSearchIp));
        mi.addSelectionListener(new ISelectionListener() {
            public void widgetSelected(SelectionEvent e) {
                shellLauncher.openIPSeekerWindow();
            }
        });
        // 
        mi = new CMenuItem(toolMenu, SWT.PUSH);
        mi.setText(menu_sys_weather);
        mi.setImage(res.getImage(Resources.icoSun));
        mi.addSelectionListener(new ISelectionListener() {
            public void widgetSelected(SelectionEvent e) {
                shellLauncher.openWeatherWindow();
            }
        });
        // ?
        mi = new CMenuItem(toolMenu, SWT.PUSH);
        mi.setText(menu_sys_temp_session);
        mi.setImage(res.getImage(Resources.icoTempSessionIM));
        mi.addSelectionListener(new ISelectionListener() {
            public void widgetSelected(SelectionEvent e) {
                InputDialog dialog = new InputDialog(main.getShell(), "Input QQ Number",
                        "Input the QQ number which you want to talk", null, null);
                if (IDialogConstants.OK_ID == dialog.open()) {
                    String value = dialog.getValue();
                    if (value == null)
                        return;
                    int qq = Util.getInt(value, 0);
                    if (qq == 0)
                        return;
                    shellLauncher.openTempSessionIMWindow(qq);
                }
            }
        });
        // separator
        final CMenuItem miSep1 = new CMenuItem(sysMenu, SWT.SEPARATOR);
        // 
        final CMenuItem miPersonalInfo = new CMenuItem(sysMenu, SWT.PUSH);
        miPersonalInfo.setText(menu_sys_personinfo);
        miPersonalInfo.setImage(res.getImage(Resources.icoPersonInfo));
        miPersonalInfo.addSelectionListener(new ISelectionListener() {
            public void widgetSelected(SelectionEvent e) {
                shellLauncher.openUserInfoWindow(main.getMyModel(), UserInfoWindow.EDITABLE);
            }
        });
        // ?
        mi = new CMenuItem(sysMenu, SWT.PUSH);
        mi.setText(menu_sys_sysopt);
        mi.setImage(res.getImage(Resources.icoSysOpt));
        mi.addSelectionListener(new ISelectionListener() {
            public void widgetSelected(SelectionEvent e) {
                shellLauncher.openSystemOptionWindow();
            }
        });
        // separator
        new CMenuItem(sysMenu, SWT.SEPARATOR);
        // 
        final CMenuItem miChangeUser = new CMenuItem(sysMenu, SWT.PUSH);
        miChangeUser.setText(menu_sys_changeuser);
        miChangeUser.setImage(res.getImage(Resources.icoChangeUser));
        miChangeUser.addSelectionListener(new ISelectionListener() {
            public void widgetSelected(SelectionEvent e) {
                main.changeUser();
            }
        });
        // separator
        final CMenuItem miSep2 = new CMenuItem(sysMenu, SWT.SEPARATOR);
        // LumaQQ
        mi = new CMenuItem(sysMenu, SWT.PUSH);
        mi.setText(menu_sys_checkupdate);
        mi.setImage(res.getImage(Resources.icoUpdate));
        mi.addSelectionListener(new ISelectionListener() {
            public void widgetSelected(SelectionEvent e) {
                shellLauncher.openCheckUpdateShell();
            }
        });
        // LumaQQ
        mi = new CMenuItem(sysMenu, SWT.PUSH);
        mi.setText(menu_sys_lumaqq_homepage);
        mi.setImage(res.getImage(Resources.icoFirefox));
        mi.addSelectionListener(new ISelectionListener() {
            public void widgetSelected(SelectionEvent e) {
                shellLauncher.goLumaQQ();
            }
        });
        // 
        mi = new CMenuItem(sysMenu, SWT.PUSH);
        mi.setText(menu_sys_about);
        mi.setImage(res.getImage(Resources.icoAbout));
        mi.addSelectionListener(new ISelectionListener() {
            public void widgetSelected(SelectionEvent e) {
                AboutDialog ad = new AboutDialog(shell);
                ad.open();
            }
        });
        // separator
        new CMenuItem(sysMenu, SWT.SEPARATOR);
        // ?
        mi = new CMenuItem(sysMenu, SWT.PUSH);
        mi.setText(menu_sys_debug);
        mi.setImage(res.getImage(Resources.icoDebug));
        mi.addSelectionListener(new ISelectionListener() {
            public void widgetSelected(SelectionEvent e) {
                new Debugger(main).open();
            }
        });
        // separator
        new CMenuItem(sysMenu, SWT.SEPARATOR);
        // ?
        final CMenuItem miRobot = new CMenuItem(sysMenu, SWT.CASCADE);
        miRobot.setText(menu_sys_robot);
        miRobot.setImage(res.getImage(Resources.icoMachine));
        robotMenu = new CMenu(miRobot);
        // separator
        final CMenuItem miRobotSeparator = new CMenuItem(sysMenu, SWT.SEPARATOR);
        // 
        mi = new CMenuItem(sysMenu, SWT.PUSH);
        mi.setText(menu_sys_exit);
        mi.setImage(res.getImage(Resources.icoExit));
        mi.addSelectionListener(new ISelectionListener() {
            public void widgetSelected(SelectionEvent e) {
                main.close();
            }
        });
        // separator
        final CMenuItem miStatusSeparator = new CMenuItem(sysMenu, SWT.SEPARATOR);
        // ???
        final CMenuItem miStatus = new CMenuItem(sysMenu, SWT.CASCADE);
        miStatus.setText(menu_sys_status);
        miStatus.setImage(res.getImage(Resources.icoLumaQQ));
        miStatus.setMenu(statusMenu);

        sysMenu.addMenuListener(new IMenuListener() {
            public void menuShown(MenuEvent e) {
                // ??
                boolean logged = main.getClient().getUser().isLoggedIn();

                initRobotMenu();
                if (LumaQQ.hasRobots()) {
                    miRobot.setVisible(true);
                    miRobotSeparator.setVisible(true);
                } else {
                    miRobot.setVisible(false);
                    miRobotSeparator.setVisible(false);
                }

                // sysmenudata0??
                // 1tray icon
                Integer loc = (Integer) sysMenu.getData();
                miStatus.setVisible(logged && loc == 1);
                miStatusSeparator.setVisible(logged && loc == 1);

                // other items
                miGroupManage.setVisible(logged);
                miFriend.setVisible(logged);
                miTool.setVisible(logged);
                miSep1.setVisible(logged);
                miPersonalInfo.setVisible(logged);
                miChangeUser.setVisible(logged);
                miSep2.setVisible(logged);
            }
        });
    }

    /**
     * ????
     */
    private void initRobotMenu() {
        if (robotInitialized)
            return;

        // robot menu items
        List<Robot> robots = LumaQQ.getRobots();
        int size = robots.size();
        for (int i = 0; i < size; i++) {
            Robot robot = robots.get(i);
            CMenuItem rItem = new CMenuItem(robotMenu, SWT.RADIO);
            rItem.setText(robot.getName());
            rItem.setData(i);
            if (i == 0)
                rItem.setSelected(true);
            rItem.addSelectionListener(new ISelectionListener() {
                public void widgetSelected(SelectionEvent event) {
                    int index = (Integer) event.item.getData();
                    client.setRobot(LumaQQ.getRobot(index));
                }
            });
        }
        // enable/disable robot
        CMenuItem mi = new CMenuItem(robotMenu, SWT.SEPARATOR);
        mi = new CMenuItem(robotMenu, SWT.PUSH);
        if (client.isRobotMode())
            mi.setText(menu_sys_robot_off);
        else
            mi.setText(menu_sys_robot_on);
        mi.addSelectionListener(new ISelectionListener() {
            public void widgetSelected(SelectionEvent event) {
                CMenuItem onOff = event.item;
                client.setRobotMode(!client.isRobotMode());
                if (client.isRobotMode())
                    onOff.setText(menu_sys_robot_off);
                else
                    onOff.setText(menu_sys_robot_on);
                if (client.getRobot() == null) {
                    for (CMenuItem mi : robotMenu.getItems()) {
                        if (mi.isSelected()) {
                            int index = (Integer) mi.getData();
                            client.setRobot(LumaQQ.getRobot(index));
                            break;
                        }
                    }
                }
            }
        });

        robotInitialized = true;
    }

    /**
     * ????
     */
    private void initStatusMenu() {
        // ???
        statusMenu = new CMenu();
        // 
        CMenuItem mi = new CMenuItem(statusMenu, SWT.PUSH);
        mi.setText(status_online);
        mi.setImage(res.getImage(Resources.icoOnline));
        mi.addSelectionListener(new ISelectionListener() {
            public void widgetSelected(SelectionEvent e) {
                main.getClient().getUser().setLoginMode(QQ.QQ_LOGIN_MODE_NORMAL);
                if (main.checkLogin(false, false)) {
                    main.getUIHelper().startStatusAnimation();
                    client.makeMeOnline();
                } else
                    client.getUser().setStatus(QQ.QQ_STATUS_ONLINE);
            }
        });
        // separator
        new CMenuItem(statusMenu, SWT.SEPARATOR);
        // ?????
        mi = new CMenuItem(statusMenu, SWT.CASCADE);
        mi.setText(status_away);
        mi.setImage(res.getImage(Resources.icoAway));
        awayMenu = new CMenu(mi);
        // 
        CMenuItem sub = new CMenuItem(awayMenu, SWT.PUSH);
        sub.setText(menu_status_away_custom);
        sub.setImage(res.getImage(Resources.icoReply));
        sub.addSelectionListener(new ISelectionListener() {
            public void widgetSelected(SelectionEvent e) {
                shellLauncher.openSystemOptionWindow().setCurrentPage(SystemOptionWindow.REPLY);
            }
        });
        new CMenuItem(awayMenu, SWT.SEPARATOR);
        // ?
        sub = new CMenuItem(awayMenu, SWT.RADIO);
        sub.setText(menu_status_away_null);
        sub.addSelectionListener(new ISelectionListener() {
            public void widgetSelected(SelectionEvent e) {
                main.getClient().getUser().setLoginMode(QQ.QQ_LOGIN_MODE_NORMAL);
                if (main.checkLogin(false, false)) {
                    main.getConfigHelper().setAutoReply(false);
                    if (client.getUser().getStatus() != QQ.QQ_STATUS_AWAY) {
                        main.getUIHelper().startStatusAnimation();
                        client.makeMeAway();
                    }
                } else
                    client.getUser().setStatus(QQ.QQ_STATUS_AWAY);
            }
        });
        // separator
        new CMenuItem(statusMenu, SWT.SEPARATOR);
        // ?
        mi = new CMenuItem(statusMenu, SWT.PUSH);
        mi.setText(status_hidden);
        mi.setImage(res.getImage(Resources.icoHidden));
        mi.addSelectionListener(new ISelectionListener() {
            public void widgetSelected(SelectionEvent e) {
                main.getClient().getUser().setLoginMode(QQ.QQ_LOGIN_MODE_HIDDEN);
                if (main.checkLogin(false, false)) {
                    if (client.getUser().getStatus() != QQ.QQ_STATUS_HIDDEN) {
                        main.getUIHelper().startStatusAnimation();
                        client.makeMeHidden();
                    }
                } else
                    client.getUser().setStatus(QQ.QQ_STATUS_HIDDEN);
            }
        });
        // separator
        new CMenuItem(statusMenu, SWT.SEPARATOR);
        // 
        mi = new CMenuItem(statusMenu, SWT.PUSH);
        mi.setText(status_offline);
        mi.setImage(res.getImage(Resources.icoOffline));
        mi.addSelectionListener(new ISelectionListener() {
            public void widgetSelected(SelectionEvent e) {
                main.checkGroupDirty();
                main.getClient().getUser().setStatus(QQ.QQ_STATUS_OFFLINE);
                main.logout();
            }
        });
    }

    /**
     * QQClient
     * 
     * @param client
     *       QQ
     */
    public void setClient(QQClient client) {
        this.client = client;
    }

    /**
     * ?????
     * 
     * @param b
     */
    public void setStatusMenuVisible(boolean b) {
        hideAllMenu();
        statusMenu.setVisible(b);
    }

    /**
     * ????
     * 
     * @param loc
     *       ???
     */
    public void setStatusMenuLocation(Point loc) {
        statusMenu.setLocation(loc);
    }

    /**
     * ???
     * 
     * @param loc
     */
    public void setGroupMenuLocation(Point loc) {
        groupMenu.setLocation(loc);
    }

    /**
     * ???
     * 
     * @param data
     */
    public void setGroupMenuData(Object data) {
        groupMenu.setData(data);
    }

    /**
     * ????
     * 
     * @param b
     */
    public void setGroupMenuVisible(boolean b) {
        hideAllMenu();
        groupMenu.setVisible(b);
    }

    /**
     * ????
     * 
     * @param loc
     */
    public void setFriendMenuLocation(Point loc) {
        friendMenu.setLocation(loc);
    }

    /**
     * ?????
     * 
     * @param b
     */
    public void setFriendMenuVisible(boolean b) {
        hideAllMenu();
        friendMenu.setVisible(b);
    }

    /**
     * ????
     * 
     * @param data
     */
    public void setFriendMenuData(Object data) {
        friendMenu.setData(data);
    }

    /**
     * ????
     * 
     * @param loc
     */
    public void setMemberMenuLocation(Point loc) {
        memberMenu.setLocation(loc);
    }

    /**
     * ?????
     * 
     * @param b
     */
    public void setMemberMenuVisible(boolean b) {
        hideAllMenu();
        memberMenu.setVisible(b);
    }

    /**
     * ????
     * 
     * @param data
     */
    public void setMemberMenuData(Object data) {
        memberMenu.setData(data);
    }

    /**
     * ???
     * 
     * @param data
     */
    public void setClusterMenuData(Object data) {
        clusterMenu.setData(data);
    }

    /**
     * ???
     * 
     * @param loc
     */
    public void setClusterMenuLocation(Point loc) {
        clusterMenu.setLocation(loc);
    }

    /**
     * ????
     * 
     * @param b
     */
    public void setClusterMenuVisible(boolean b) {
        hideAllMenu();
        clusterMenu.setVisible(b);
    }

    public void setPlusMenuVisible(boolean b) {
        hideAllMenu();
        plusMenu.setVisible(b);
    }

    public void setPlusMenuLocation(Point loc) {
        plusMenu.setLocation(loc);
    }

    public boolean isPlusMenuVisible() {
        return plusMenu.isVisible();
    }

    public void setDialogContainerMenuVisible(boolean b) {
        hideAllMenu();
        dialogContainerMenu.setVisible(b);
    }

    public void setDialogContainerMenuData(Object data) {
        dialogContainerMenu.setData(data);
    }

    public void setDialogContainerMenuLocation(Point loc) {
        dialogContainerMenu.setLocation(loc);
    }

    /**
     * ????
     * 
     * @param b
     */
    public void setSystemMenuVisible(boolean b) {
        hideAllMenu();
        sysMenu.setVisible(b);
    }

    /**
     * ??data
     * 
     * @param data
     */
    public void setSystemMenuData(Object data) {
        sysMenu.setData(data);
    }

    /**
     * @return
     *       true????
     */
    public boolean isSystemMenuVisible() {
        return sysMenu.isVisible();
    }

    public void setSystemMenuLocation(Point loc) {
        sysMenu.setLocation(loc);
    }

    public void setSystemMenuLocation(int x, int y) {
        sysMenu.setLocation(x, y);
    }

    public void setSubjectMenuVisible(boolean b) {
        hideAllMenu();
        subjectMenu.setVisible(b);
    }

    public void setSubjectMenuData(Object data) {
        subjectMenu.setData(data);
    }

    public void setSubjectMenuLocation(Point loc) {
        subjectMenu.setLocation(loc);
    }

    public void setOrganizationContainerMenuVisible(boolean b) {
        hideAllMenu();
        organizationContainerMenu.setVisible(b);
    }

    public void setOrganizationContainerMenuData(Object data) {
        organizationContainerMenu.setData(data);
    }

    public void setOrganizationContainerMenuLocation(Point loc) {
        organizationContainerMenu.setLocation(loc);
    }

    public void setOrganizationMenuVisible(boolean b) {
        hideAllMenu();
        organizationMenu.setVisible(b);
    }

    public void setOrganizationMenuData(Object data) {
        organizationMenu.setData(data);
    }

    public void setOrganizationMenuLocation(Point loc) {
        organizationMenu.setLocation(loc);
    }

    public void setDiskMenuLocation(Point loc) {
        diskMenu.setLocation(loc);
    }

    public void setDiskMenuData(Object data) {
        diskMenu.setData(data);
    }

    public void setDiskMenuVisible(boolean b) {
        hideAllMenu();
        diskMenu.setVisible(b);
    }

    /**
     * ?????
     */
    @SuppressWarnings("unchecked")
    public void renewAawyMenu() {
        int count = awayMenu.getItemCount();
        List<String> autoReplies = main.getConfigHelper().getReplies().getAutoReply();
        int size = autoReplies.size();
        // 3??3separator??
        int loop = Math.min(count, 3 + size);
        for (int i = 3, j = 0; i < loop; i++) {
            CMenuItem mi = awayMenu.getItem(i);
            mi.setText(autoReplies.get(j++));
        }
        // ????????
        size -= count - 3;
        if (size > 0) { // 0?
            for (int i = 0; i < size; i++) {
                CMenuItem mi = new CMenuItem(awayMenu, SWT.RADIO);
                final int index = count - 3 + i;
                mi.setText(autoReplies.get(index));
                mi.addSelectionListener(new ISelectionListener() {
                    public void widgetSelected(SelectionEvent e) {
                        main.getClient().getUser().setLoginMode(QQ.QQ_LOGIN_MODE_NORMAL);
                        if (main.checkLogin(false, false)) {
                            main.getConfigHelper().setAutoReply(true);
                            main.getConfigHelper().getReplies().setCurrentAutoReply(index);
                            if (client.getUser().getStatus() != QQ.QQ_STATUS_AWAY) {
                                main.getUIHelper().startStatusAnimation();
                                client.makeMeAway();
                            }
                        } else {
                            main.getConfigHelper().setAutoReply(true);
                            main.getConfigHelper().getReplies().setCurrentAutoReply(index);
                            client.getUser().setStatus(QQ.QQ_STATUS_AWAY);
                        }
                    }
                });
            }
        } else if (size < 0) { // ?0??
            size = Math.abs(size);
            for (int i = size - 1; i >= 0; i--) {
                CMenuItem mi = awayMenu.getItem(loop + i);
                mi.dispose();
            }
        }
    }

    /**
     * ????
     * MagicLinux 1.2????
     * ?
     */
    public void hideAllMenu() {
        clusterMenu.setVisible(false);
        dialogContainerMenu.setVisible(false);
        friendMenu.setVisible(false);
        groupMenu.setVisible(false);
        memberMenu.setVisible(false);
        organizationContainerMenu.setVisible(false);
        organizationMenu.setVisible(false);
        statusMenu.setVisible(false);
        subjectMenu.setVisible(false);
        sysMenu.setVisible(false);
        plusMenu.setVisible(false);
        diskMenu.setVisible(false);
    }
}