Метки услуг

Материал из BiTel WiKi

(Различия между версиями)
Перейти к: навигация, поиск
(Клиентские классы)
м (переименовал «Service labels» в «Метки услуг»)
 
(3 промежуточные версии не показаны)
Строка 7: Строка 7:
Решение состоит из серверного API и клиентского интерфейса.
Решение состоит из серверного API и клиентского интерфейса.
-
Решение является упрощённой копипастой работы с метками тарифов.
+
Решение является упрощённой копипастой стандартной работы с метками тарифов.
 +
 
 +
[[Файл:service_labels_1.png]]
= Общие классы =
= Общие классы =
Строка 615: Строка 617:
module.tab.3.class=bitel.billing.module.services.npay.ServiceLabelModulePanel
module.tab.3.class=bitel.billing.module.services.npay.ServiceLabelModulePanel
module.tab.3.title=\u0413\u0440\u0443\u043F\u043F\u044B \u0443\u0441\u043B\u0443\u0433
module.tab.3.title=\u0413\u0440\u0443\u043F\u043F\u044B \u0443\u0441\u043B\u0443\u0433
 +
</source>
 +
 +
Собственно панель:
 +
<source lang=java>
 +
package bitel.billing.module.services.npay;
 +
 +
import bitel.billing.module.common.BGControlPanelListSelect;
 +
import bitel.billing.module.common.BGTextField;
 +
import bitel.billing.module.common.BGTitleBorder;
 +
import ru.bitel.bgbilling.client.common.BGSplitPane;
 +
import ru.bitel.bgbilling.client.common.BGUPanel;
 +
import ru.bitel.bgbilling.client.common.BGUTable;
 +
import ru.bitel.bgbilling.client.util.ClientUtils;
 +
import ru.bitel.bgbilling.common.BGException;
 +
import ru.bitel.bgbilling.kernel.module.common.service.ModuleService;
 +
import ru.bitel.bgbilling.kernel.module.common.service.ServiceLabelService;
 +
import ru.bitel.common.client.BGUAction;
 +
import ru.bitel.common.client.table.BGTableModel;
 +
import ru.dsi.bgbilling.kernel.module.client.ServiceLabelTree;
 +
import ru.dsi.bgbilling.kernel.module.common.bean.ServiceItem;
 +
import ru.dsi.bgbilling.kernel.module.common.bean.ServiceLabelItem;
 +
import ru.dsi.bgbilling.kernel.module.common.bean.ServiceLabelTreeCellRenderer;
 +
 +
import javax.swing.*;
 +
import javax.swing.event.CellEditorListener;
 +
import javax.swing.tree.*;
 +
import java.awt.*;
 +
import java.awt.datatransfer.DataFlavor;
 +
import java.awt.datatransfer.Transferable;
 +
import java.awt.datatransfer.UnsupportedFlavorException;
 +
import java.awt.dnd.*;
 +
import java.awt.event.*;
 +
import java.beans.PropertyChangeEvent;
 +
import java.beans.PropertyChangeListener;
 +
import java.io.IOException;
 +
import java.util.EventObject;
 +
import java.util.HashSet;
 +
import java.util.List;
 +
 +
/**
 +
* Панель для редактирования меток услуг.
 +
* Метки услуг - аналог меток тарифных планов, только для услуг (service).
 +
* Метки хранятся в таблицах custom_service_label и custom_service_label_link
 +
*/
 +
public class ServiceLabelModulePanel extends BGUPanel {
 +
    private BGControlPanelListSelect serviceModuleList = new BGControlPanelListSelect();
 +
    private JPanel labelModePanel = null;
 +
    private CardLayout cardLayout1 = new CardLayout();
 +
    private JPanel rightPanel = new JPanel(this.cardLayout1);
 +
    private JPopupMenu popupFilterMenu = new JPopupMenu();
 +
    private JPopupMenu popupEditorMenu = new JPopupMenu();
 +
    private BGTextField name = new BGTextField();
 +
    /**
 +
    * Текущая выбранная для редактирования услуга
 +
    */
 +
    private int serviceId = 0;
 +
    private String serviceTitle = "";
 +
 +
    //дерево меток в фильтре сервисов
 +
    private ServiceLabelTree filterLabelTree = new ServiceLabelTree();
 +
    //дерево меток в редакторе сервиса
 +
    private ServiceLabelTree serviceLabelTree = new ServiceLabelTree();
 +
    private ServiceLabelService wsServiceLabel = getContext().getPort(ServiceLabelService.class, 0);
 +
    private ModuleService wsModule = getContext().getPort(ModuleService.class, 0);
 +
 +
    private BGTableModel<ServiceItem> serviceModel = new BGTableModel<ServiceItem>("service")
 +
    {
 +
        protected void initColumns()
 +
        {
 +
            addColumn("ID", 60, 60, 60, "id", true);
 +
            addColumn("Название", "title", true);
 +
            addColumn("Модуль", "moduleTitle", true);
 +
            addColumn("Используется", -1, 50, 50, "using", true);
 +
            addColumn("Меток", 150, 150, 150, "labelCount", true);
 +
        }
 +
    };
 +
    private BGUTable serviceTable = new BGUTable(this.serviceModel);
 +
 +
    @Override
 +
    protected void jbInit() throws Exception {
 +
 +
        this.filterLabelTree.addPropertyChangeListener(new PropertyChangeListener()
 +
        {
 +
            public void propertyChange(PropertyChangeEvent event)
 +
            {
 +
                if ("changeSelected".equals(event.getPropertyName()))
 +
                {
 +
                    ServiceLabelModulePanel.this.setData();
 +
                }
 +
            }
 +
        });
 +
 +
        this.filterLabelTree.setCellEditor(new DefaultTreeCellEditor(this.filterLabelTree,
 +
                new DefaultTreeCellRenderer()
 +
                {
 +
                }
 +
                , new ServiceTreeCellEditor()));
 +
 +
        setLabelTreeData(this.filterLabelTree, -1);
 +
 +
        this.serviceTable.setSelectionMode(ListSelectionModel.SINGLE_SELECTION);
 +
        this.serviceTable.addMouseListener(new MouseAdapter()
 +
        {
 +
            public void mouseClicked(MouseEvent event)
 +
            {
 +
                if ((SwingUtilities.isLeftMouseButton(event)) && (event.getClickCount() == 2) && (ServiceLabelModulePanel.this.serviceTable.isEnabled()))
 +
                {
 +
                    ServiceLabelModulePanel.this.initServiceId();
 +
                    ServiceLabelModulePanel.this.showServiceEditor();
 +
                }
 +
            }
 +
        });
 +
 +
        JButton commitButton = new JButton("Применить");
 +
        commitButton.addActionListener(new ActionListener()
 +
        {
 +
            public void actionPerformed(ActionEvent e)
 +
            {
 +
                ServiceLabelModulePanel.this.updateService();
 +
            }
 +
        });
 +
        JButton cancelButton = new JButton("Закрыть");
 +
        cancelButton.addActionListener(new ActionListener()
 +
        {
 +
            public void actionPerformed(ActionEvent e)
 +
            {
 +
                ServiceLabelModulePanel.this.setData();
 +
            }
 +
        });
 +
 +
        JPanel namePanel = new JPanel(new GridBagLayout());
 +
        namePanel.setBorder(new BGTitleBorder(" Услуга "));
 +
        this.name.setEditable(false);//Имя услуги просто отображаем - редактировать нельзя
 +
        namePanel.add(this.name, new GridBagConstraints(0, 0, 1, 1, 1.0D, 0.0D, 10, 1, new Insets(0, 5, 5, 5), 0, 0));
 +
 +
        JPanel commitPanel = new JPanel(new GridBagLayout());
 +
        commitPanel.add(Box.createHorizontalGlue(), new GridBagConstraints(0, 0, 1, 1, 1.0D, 0.0D, 13, 1, new Insets(5, 0, 5, 5), 0, 0));
 +
        commitPanel.add(commitButton, new GridBagConstraints(1, 0, 1, 1, 0.0D, 0.0D, 13, 0, new Insets(5, 5, 5, 5), 0, 0));
 +
        commitPanel.add(cancelButton, new GridBagConstraints(2, 0, 1, 1, 0.0D, 0.0D, 13, 0, new Insets(5, 5, 5, 5), 0, 0));
 +
 +
        JPanel labelPanel = new JPanel(new GridBagLayout());
 +
        labelPanel.setBorder(new BGTitleBorder(" Метки "));
 +
        labelPanel.add(new JScrollPane(this.serviceLabelTree), new GridBagConstraints(0, 0, 1, 1, 1.0D, 1.0D, 10, 1, new Insets(0, 5, 5, 5), 0, 0));
 +
 +
        JPanel preferencesPanel = new JPanel(new GridBagLayout());
 +
        preferencesPanel.add(namePanel, new GridBagConstraints(0, 0, 2, 1, 1.0D, 0.0D, 10, 1, new Insets(0, 5, 5, 5), 0, 0));
 +
        preferencesPanel.add(labelPanel, new GridBagConstraints(0, 1, 1, 1, 1.0D, 1.0D, 10, 1, new Insets(0, 5, 5, 5), 0, 0));
 +
        preferencesPanel.add(commitPanel, new GridBagConstraints(0, 2, 2, 1, 1.0D, 0.0D, 10, 2, new Insets(0, 5, 5, 5), 0, 0));
 +
 +
        this.rightPanel.add(preferencesPanel, "editor");
 +
        this.rightPanel.add(getServiceListPanel(), "list");
 +
 +
        setLayout(new GridBagLayout());
 +
        add(new BGSplitPane(1, getFilterPanel(), this.rightPanel), new GridBagConstraints(0, 0, 1, 1, 1.0D, 1.0D, 10, 1, new Insets(0, 0, 0, 0), 0, 0));
 +
 +
        new TreeDragSource(this.filterLabelTree, 2);
 +
        new TreeDropTarget(this.filterLabelTree);
 +
        setData();
 +
    }
 +
 +
    private void setData() {
 +
        try {
 +
            this.serviceModel.setData(this.wsServiceLabel.getServiceList(new HashSet<Integer>(
 +
                    this.serviceModuleList.getListIds()),
 +
                    this.filterLabelTree.getSelectedIds()));
 +
            if (this.serviceModuleList.getList().getModel().getSize() == 0){
 +
                ClientUtils.buildList(this.serviceModuleList.getList(), this.wsModule.moduleList());
 +
            }
 +
        } catch (BGException ex) {
 +
            this.processException(ex);
 +
        }
 +
 +
        showServiceTable();
 +
    }
 +
 +
    private TreePath getSelectionPath(ServiceLabelTree filterLabelTree, String message)
 +
    {
 +
        TreePath treePath = filterLabelTree.getSelectionPath();
 +
        if (treePath == null)
 +
        {
 +
            JOptionPane.showMessageDialog(this, message, "Сообщение об ошибке", JOptionPane.ERROR_MESSAGE);
 +
        }
 +
        return treePath;
 +
    }
 +
 +
    private void updateService(){
 +
        try{
 +
            this.wsServiceLabel.setServiceLabelTreeItemList(this.serviceId, this.serviceLabelTree.getSelectedItems());
 +
            updateFilterLabelTreeData(this.wsServiceLabel.getServiceLabelTreeItemList(-1));
 +
        }catch (BGException ex){
 +
            processException(ex);
 +
        }
 +
    }
 +
 +
    private void setLabelTreeData(ServiceLabelTree labelTree, int serviceId)
 +
    {
 +
        try
 +
        {
 +
            labelTree.setData(getContext().getPort(ServiceLabelService.class).getServiceLabelTreeItemList(serviceId));
 +
        }
 +
        catch (BGException ex)
 +
        {
 +
            processException(ex);
 +
        }
 +
    }
 +
 +
    private void updateFilterLabelTreeData(List<ServiceLabelItem> items)
 +
    {
 +
        DefaultTreeModel model = (DefaultTreeModel)this.filterLabelTree.getModel();
 +
        for (ServiceLabelItem serviceLabelItem : items)
 +
        {
 +
            DefaultMutableTreeNode serviceLabelTreeNode = (DefaultMutableTreeNode)model.getRoot();
 +
            while (serviceLabelTreeNode != null)
 +
            {
 +
                Object object = serviceLabelTreeNode.getUserObject();
 +
                if ((object instanceof ServiceLabelItem))
 +
                {
 +
                    ServiceLabelItem item = (ServiceLabelItem)object;
 +
                    if (item.getId() == serviceLabelItem.getId())
 +
                    {
 +
                        item.setTitle(serviceLabelItem.getTitle());
 +
                        item.setServiceLinkCount(serviceLabelItem.getServiceLinkCount());
 +
                        model.nodeChanged(serviceLabelTreeNode);
 +
                        break;
 +
                    }
 +
                }
 +
                serviceLabelTreeNode = serviceLabelTreeNode.getNextNode();
 +
            }
 +
        }
 +
    }
 +
 +
    private void initServiceId()
 +
    {
 +
        this.serviceId = this.serviceModel.getSelectedRow().getId();
 +
        this.serviceTitle = this.serviceModel.getSelectedRow().getTitle();
 +
 +
    }
 +
 +
    private void showServiceEditor()
 +
    {
 +
        setFilterServiceEnabled(false);
 +
        this.serviceLabelTree.setComponentPopupMenu(this.popupFilterMenu);
 +
        this.filterLabelTree.setComponentPopupMenu(null);
 +
        this.cardLayout1.show(this.rightPanel, "editor");
 +
        setServiceData();
 +
    }
 +
 +
    private void showServiceTable()
 +
    {
 +
        setFilterServiceEnabled(true);
 +
        this.serviceLabelTree.setComponentPopupMenu(null);
 +
        this.filterLabelTree.setComponentPopupMenu(this.popupFilterMenu);
 +
        this.cardLayout1.show(this.rightPanel, "list");
 +
    }
 +
 +
    private void setFilterServiceEnabled(boolean enabled)
 +
    {
 +
        this.filterLabelTree.setEnabled(enabled);
 +
        this.serviceModuleList.setEnabled(enabled);
 +
        this.labelModePanel.setEnabled(enabled);
 +
    }
 +
 +
    public void setServiceData()
 +
    {
 +
        if (this.serviceId < 1)
 +
        {
 +
            return;
 +
        }
 +
 +
        this.name.setText(this.serviceTitle);
 +
        //this.serviceId = Utils.parseInt(XMLUtils.getAttribute(plan, "id", "-1"));
 +
        //this.serviceTitle.setText(XMLUtils.getAttribute(plan, "title", "Без названия ;-(("));
 +
 +
        setLabelTreeData(this.serviceLabelTree, this.serviceId);
 +
    }
 +
 +
    private JPanel getServiceListPanel()
 +
    {
 +
        JPanel panel = new JPanel(new GridBagLayout());
 +
        panel.setBorder(new BGTitleBorder(" Услуги "));
 +
        panel.add(new JScrollPane(this.serviceTable), new GridBagConstraints(0, 0, 3, 1, 1.0D, 1.0D, 10, 1, new Insets(0, 5, 5, 5), 0, 0));
 +
        return panel;
 +
    }
 +
 +
    private JPanel getFilterPanel()
 +
    {
 +
        this.filterLabelTree.setComponentPopupMenu(this.popupFilterMenu);
 +
        this.popupEditorMenu.add(new JMenuItem(new BGUAction("addServiceLabel", "Добавить метку")
 +
        {
 +
            public void actionPerformed(ActionEvent e)
 +
            {
 +
                TreePath treePath = ServiceLabelModulePanel.this.getSelectionPath(ServiceLabelModulePanel.this.filterLabelTree, "Выберите родительскую метку.");
 +
                if (treePath != null)
 +
                {
 +
                    Object selectedObject = treePath.getLastPathComponent();
 +
                    if ((selectedObject instanceof DefaultMutableTreeNode))
 +
                    {
 +
                        DefaultMutableTreeNode tariffLabelTreeNode = (DefaultMutableTreeNode)selectedObject;
 +
                        Object userObject = tariffLabelTreeNode.getUserObject();
 +
                        if ((userObject instanceof ServiceLabelItem))
 +
                        {
 +
                            ServiceLabelItem newServiceLabelItem = new ServiceLabelItem();
 +
                            newServiceLabelItem.setId(-1);
 +
                            newServiceLabelItem.setParentId(((ServiceLabelItem) userObject).getId());
 +
                            newServiceLabelItem.setTitle("Новая метка");
 +
 +
                            DefaultMutableTreeNode newTariffLabelTreeNode = new DefaultMutableTreeNode();
 +
                            newTariffLabelTreeNode.setUserObject(newServiceLabelItem);
 +
 +
                            DefaultTreeModel defaultTreeModel = (DefaultTreeModel)ServiceLabelModulePanel.this.filterLabelTree.getModel();
 +
                            defaultTreeModel.insertNodeInto(newTariffLabelTreeNode, tariffLabelTreeNode, tariffLabelTreeNode.getChildCount());
 +
                            ServiceLabelModulePanel.this.filterLabelTree.expandPath(new TreePath(tariffLabelTreeNode.getPath()));
 +
                            ServiceLabelModulePanel.this.filterLabelTree.scrollPathToVisible(new TreePath(tariffLabelTreeNode.getPath()));
 +
                            try
 +
                            {
 +
                                newServiceLabelItem.setId(ServiceLabelModulePanel.this.getContext().getPort(ServiceLabelService.class).updateServiceLabelTreeItem(newServiceLabelItem));
 +
                            }
 +
                            catch (BGException ex)
 +
                            {
 +
                                ServiceLabelModulePanel.this.processException(ex);
 +
                            }
 +
                        }
 +
                    }
 +
                }
 +
            }
 +
        }));
 +
 +
        this.popupEditorMenu.add(new JMenuItem(new BGUAction("renameServiceLabel", "Переименовать метку")
 +
        {
 +
            public void actionPerformed(ActionEvent e)
 +
            {
 +
                TreePath treePath = ServiceLabelModulePanel.this.getSelectionPath(ServiceLabelModulePanel.this.filterLabelTree, "Выберите метку");
 +
                if (treePath != null)
 +
                {
 +
                    ServiceLabelModulePanel.this.filterLabelTree.startEditingAtPath(treePath);
 +
                }
 +
            }
 +
        }));
 +
        this.popupEditorMenu.add(new JMenuItem(new BGUAction("dropTarifLabel", "Удалить метку")
 +
        {
 +
            public void actionPerformed(ActionEvent e)
 +
            {
 +
                TreePath treePath = ServiceLabelModulePanel.this.getSelectionPath(ServiceLabelModulePanel.this.filterLabelTree, "Выберите метку");
 +
                if (treePath != null)
 +
                {
 +
                    Object selectedObject = treePath.getLastPathComponent();
 +
                    if ((selectedObject instanceof DefaultMutableTreeNode))
 +
                    {
 +
                        DefaultMutableTreeNode serviceLabelTreeNode = (DefaultMutableTreeNode)selectedObject;
 +
                        if (serviceLabelTreeNode.isRoot())
 +
                        {
 +
                            JOptionPane.showMessageDialog(ServiceLabelModulePanel.this, "Корневой элемент удалить нельзя.", "Сообщение об ошибке", JOptionPane.ERROR_MESSAGE);
 +
                        }
 +
                        else if (!serviceLabelTreeNode.isLeaf())
 +
                        {
 +
                            JOptionPane.showMessageDialog(ServiceLabelModulePanel.this, "Удалить нельзя, т.к. метка содержит дочерние метки, удалите сначала их.", "Сообщение об ошибке", JOptionPane.ERROR_MESSAGE);
 +
                        }
 +
                        else
 +
                        {
 +
                            Object userObject = serviceLabelTreeNode.getUserObject();
 +
                            if ((userObject instanceof ServiceLabelItem))
 +
                            {
 +
                                boolean removeFlag = true;
 +
                                ServiceLabelItem serviceLabelItem = (ServiceLabelItem)userObject;
 +
                                int serviceCount = serviceLabelItem.getServiceLinkCount();
 +
                                if (serviceCount > 0)
 +
                                {
 +
                                    removeFlag = JOptionPane.showConfirmDialog(ServiceLabelModulePanel.this, "Метка используется в услугах (" + serviceCount + ").\nПодтвердите удаление.", "Запрос подтверждения", JOptionPane.YES_NO_OPTION) == 0;
 +
                                }
 +
                                if (removeFlag)
 +
                                {
 +
                                    ((DefaultTreeModel)ServiceLabelModulePanel.this.filterLabelTree.getModel()).removeNodeFromParent(serviceLabelTreeNode);
 +
                                    try
 +
                                    {
 +
                                        ServiceLabelModulePanel.this.getContext().getPort(ServiceLabelService.class).removeServiceLabelTreeItem(serviceLabelItem.getId());
 +
                                    }
 +
                                    catch (BGException ex)
 +
                                    {
 +
                                        ServiceLabelModulePanel.this.processException(ex);
 +
                                    }
 +
                                }
 +
                            }
 +
                        }
 +
                    }
 +
                }
 +
            }
 +
        }));
 +
 +
        this.popupFilterMenu.add(new JMenuItem(new BGUAction("selectParent", "Выбрать всех родителей")
 +
        {
 +
            public void actionPerformed(ActionEvent event)
 +
            {
 +
                JMenuItem menuItem = (JMenuItem)event.getSource();
 +
                ServiceLabelTree tree = (ServiceLabelTree)((JPopupMenu)menuItem.getParent()).getInvoker();
 +
                Object selectedObject = tree.getLastSelectedPathComponent();
 +
                if ((selectedObject instanceof DefaultMutableTreeNode))
 +
                {
 +
                    DefaultMutableTreeNode serviceLabelTreeNode = (DefaultMutableTreeNode)selectedObject;
 +
                    while (serviceLabelTreeNode != null)
 +
                    {
 +
                        Object userObject = serviceLabelTreeNode.getUserObject();
 +
                        if ((userObject instanceof ServiceLabelItem))
 +
                        {
 +
                            ((ServiceLabelItem)userObject).setSelected(true);
 +
                            ((DefaultTreeModel)tree.getModel()).nodeChanged(serviceLabelTreeNode);
 +
                        }
 +
                        serviceLabelTreeNode = (DefaultMutableTreeNode)serviceLabelTreeNode.getParent();
 +
                    }
 +
                }
 +
                tree.firePropertyChange("changeSelected", false, true);
 +
            }
 +
        }));
 +
        this.popupFilterMenu.add(new JMenuItem(new BGUAction("selectChildren", "Выбрать всех детей")
 +
        {
 +
            public void actionPerformed(ActionEvent event)
 +
            {
 +
                JMenuItem menuItem = (JMenuItem)event.getSource();
 +
                ServiceLabelTree tree = (ServiceLabelTree)((JPopupMenu)menuItem.getParent()).getInvoker();
 +
                Object selectedObject = tree.getLastSelectedPathComponent();
 +
                if ((selectedObject instanceof DefaultMutableTreeNode))
 +
                {
 +
                    DefaultMutableTreeNode serviceLabelTreeNode = (DefaultMutableTreeNode)selectedObject;
 +
                    int selectNodeLevel = serviceLabelTreeNode.getLevel();
 +
                    while (serviceLabelTreeNode != null)
 +
                    {
 +
                        Object userObject = serviceLabelTreeNode.getUserObject();
 +
                        if ((userObject instanceof ServiceLabelItem))
 +
                        {
 +
                            ((ServiceLabelItem)userObject).setSelected(true);
 +
                            ((DefaultTreeModel)tree.getModel()).nodeChanged(serviceLabelTreeNode);
 +
                        }
 +
                        serviceLabelTreeNode = serviceLabelTreeNode.getNextNode();
 +
                        if ((serviceLabelTreeNode != null) && (serviceLabelTreeNode.getLevel() <= selectNodeLevel))
 +
                        {
 +
                            break;
 +
                        }
 +
                    }
 +
                }
 +
                tree.firePropertyChange("changeSelected", false, true);
 +
            }
 +
        }));
 +
        this.popupFilterMenu.add(new JMenuItem(new BGUAction("selectReset", "Сброс выделения")
 +
        {
 +
            public void actionPerformed(ActionEvent event)
 +
            {
 +
                JMenuItem menuItem = (JMenuItem)event.getSource();
 +
                ServiceLabelTree tree = (ServiceLabelTree)((JPopupMenu)menuItem.getParent()).getInvoker();
 +
                DefaultMutableTreeNode node = ((DefaultMutableTreeNode)tree.getModel().getRoot()).getNextNode();
 +
                while (node != null)
 +
                {
 +
                    Object userObject = node.getUserObject();
 +
                    if ((userObject instanceof ServiceLabelItem))
 +
                    {
 +
                        ((ServiceLabelItem)userObject).setSelected(false);
 +
                        ((DefaultTreeModel)tree.getModel()).nodeChanged(node);
 +
                    }
 +
                    node = node.getNextNode();
 +
                }
 +
                tree.firePropertyChange("changeSelected", false, true);
 +
            }
 +
        }));
 +
        ActionListener modeActionListener = new ActionListener()
 +
        {
 +
            public void actionPerformed(ActionEvent event)
 +
            {
 +
                ServiceLabelModulePanel.this.switchLabelMode(event.getActionCommand());
 +
            }
 +
        };
 +
        Dimension dimension = new Dimension(100, 200);
 +
        this.serviceModuleList.setMinimumSize(dimension);
 +
        this.serviceModuleList.setPreferredSize(dimension);
 +
        this.serviceModuleList.addPropertyChangeListener(new PropertyChangeListener()
 +
        {
 +
            public void propertyChange(PropertyChangeEvent event)
 +
            {
 +
                if (("itemChange".equals(event.getPropertyName())) && (ServiceLabelModulePanel.this.serviceModuleList.isEnabled()))
 +
                {
 +
                    ServiceLabelModulePanel.this.setData();
 +
                }
 +
            }
 +
        });
 +
        this.labelModePanel = new JPanel(new GridBagLayout())
 +
        {
 +
            public void setEnabled(boolean enabled)
 +
            {
 +
                super.setEnabled(enabled);
 +
                for (int index = 0; index < getComponentCount(); index++)
 +
                {
 +
                    getComponent(index).setEnabled(enabled);
 +
                }
 +
            }
 +
        };
 +
        ButtonGroup modeButtonGroup = new ButtonGroup();
 +
        this.labelModePanel.add(new JLabel("Метки:"), new GridBagConstraints(0, 0, 1, 1, 1.0D, 0.0D, 18, 0, new Insets(0, 0, 0, 5), 0, 0));
 +
        this.labelModePanel.add(new ModeButton("filter", modeButtonGroup, modeActionListener, "Фильтр"), new GridBagConstraints(1, 0, 1, 1, 0.0D, 0.0D, 10, 0, new Insets(0, 0, 0, 0), 0, 0));
 +
        this.labelModePanel.add(new ModeButton("editor", modeButtonGroup, modeActionListener, "Редактор"), new GridBagConstraints(2, 0, 1, 1, 0.0D, 0.0D, 10, 0, new Insets(0, 0, 0, 0), 0, 0));
 +
 +
        modeButtonGroup.setSelected(modeButtonGroup.getElements().nextElement().getModel(), true);
 +
 +
        int y = 0;
 +
        JPanel panel = new JPanel(new GridBagLayout());
 +
        panel.setBorder(new BGTitleBorder(" Фильтр "));
 +
        panel.add(new JLabel("Модули:"), new GridBagConstraints(0, y++, 2, 1, 0.0D, 0.0D, 17, 0, new Insets(0, 5, 0, 5), 0, 0));
 +
        panel.add(this.serviceModuleList, new GridBagConstraints(0, y++, 2, 1, 1.0D, 0.0D, 10, 2, new Insets(0, 0, 5, 0), 0, 0));
 +
        panel.add(this.labelModePanel, new GridBagConstraints(0, y++, 2, 1, 0.0D, 0.0D, 17, 2, new Insets(0, 5, 5, 5), 0, 0));
 +
        //noinspection UnusedAssignment
 +
        panel.add(new JScrollPane(this.filterLabelTree), new GridBagConstraints(0, y++, 2, 1, 1.0D, 1.0D, 10, 1, new Insets(0, 5, 5, 5), 0, 0));
 +
        return panel;
 +
    }
 +
 +
    private void switchLabelMode(String mode)
 +
    {
 +
        if ("editor".equals(mode))
 +
        {
 +
            this.serviceTable.setEnabled(false);
 +
            this.serviceModuleList.setEnabled(false);
 +
 +
            this.filterLabelTree.setEditable(true);
 +
            this.filterLabelTree.offNodeSelectionListener();
 +
            this.filterLabelTree.setComponentPopupMenu(this.popupEditorMenu);
 +
            this.filterLabelTree.setCellRenderer(new ModeEditorTreeCellRenderer());
 +
        }
 +
        else
 +
        {
 +
            this.serviceTable.setEnabled(true);
 +
            this.serviceModuleList.setEnabled(true);
 +
 +
            this.filterLabelTree.setEditable(false);
 +
            this.filterLabelTree.onNodeSelectionListener();
 +
            this.filterLabelTree.setComponentPopupMenu(this.popupFilterMenu);
 +
            this.filterLabelTree.setCellRenderer(new ServiceLabelTreeCellRenderer());
 +
        }
 +
    }
 +
 +
    class ModeEditorTreeCellRenderer extends DefaultTreeCellRenderer
 +
    {
 +
        public ModeEditorTreeCellRenderer()
 +
        {
 +
            setOpenIcon(ClientUtils.getIcon("node.png"));
 +
            setClosedIcon(ClientUtils.getIcon("node.png"));
 +
            setLeafIcon(ClientUtils.getIcon("leaf.png"));
 +
        }
 +
    }
 +
 +
    class TransferableServiceLabelItem
 +
            implements Transferable
 +
    {
 +
        DataFlavor SERVICE_LABEL_ITEM_FLAVOR = new DataFlavor(ServiceLabelItem.class, "ServiceLabelItem");
 +
        DataFlavor[] flavors = { this.SERVICE_LABEL_ITEM_FLAVOR };
 +
        Object object;
 +
 +
        public TransferableServiceLabelItem(Object object)
 +
        {
 +
            this.object = object;
 +
        }
 +
 +
        public synchronized DataFlavor[] getTransferDataFlavors()
 +
        {
 +
            return this.flavors;
 +
        }
 +
 +
        public boolean isDataFlavorSupported(DataFlavor flavor)
 +
        {
 +
            return flavor.getRepresentationClass() == ServiceLabelItem.class;
 +
        }
 +
 +
        public synchronized Object getTransferData(DataFlavor flavor)
 +
                throws UnsupportedFlavorException, IOException
 +
        {
 +
            if (isDataFlavorSupported(flavor))
 +
            {
 +
                return this.object;
 +
            }
 +
 +
            throw new UnsupportedFlavorException(flavor);
 +
        }
 +
    }
 +
 +
    class TreeDragSource implements DragSourceListener, DragGestureListener {
 +
        DragSource source;
 +
        DragGestureRecognizer recognizer;
 +
        ServiceLabelModulePanel.TransferableServiceLabelItem transferable;
 +
        DefaultMutableTreeNode oldNode;
 +
        JTree sourceTree;
 +
 +
        public TreeDragSource(JTree tree, int actions) {
 +
            this.sourceTree = tree;
 +
            this.source = new DragSource();
 +
            this.recognizer = this.source.createDefaultDragGestureRecognizer(this.sourceTree, actions, this);
 +
        }
 +
 +
        public void dragGestureRecognized(DragGestureEvent event)
 +
        {
 +
            TreePath path = this.sourceTree.getSelectionPath();
 +
            if ((path != null) && (path.getPathCount() > 1))
 +
            {
 +
                this.oldNode = ((DefaultMutableTreeNode)path.getLastPathComponent());
 +
                if ((this.oldNode.isLeaf()) && (this.sourceTree.isEditable()))
 +
                {
 +
                    this.transferable = new ServiceLabelModulePanel.TransferableServiceLabelItem(this.oldNode.getUserObject());
 +
                    event.startDrag(DragSource.DefaultMoveDrop, this.transferable, this);
 +
                }
 +
            }
 +
        }
 +
 +
        public void dragEnter(DragSourceDragEvent dragSourceDragEvent)
 +
        {
 +
        }
 +
 +
        public void dragExit(DragSourceEvent dragSourceEvent)
 +
        {
 +
        }
 +
 +
        public void dragOver(DragSourceDragEvent dragSourceDragEvent)
 +
        {
 +
        }
 +
 +
        public void dropActionChanged(DragSourceDragEvent dragSourceDragEvent)
 +
        {
 +
        }
 +
 +
        public void dragDropEnd(DragSourceDropEvent event)
 +
        {
 +
            if ((event.getDropSuccess()) && (event.getDropAction() == 2))
 +
            {
 +
                ((DefaultTreeModel)this.sourceTree.getModel()).removeNodeFromParent(this.oldNode);
 +
            }
 +
        }
 +
    }
 +
 +
    class TreeDropTarget
 +
            implements DropTargetListener
 +
    {
 +
        DropTarget target;
 +
        JTree targetTree;
 +
 +
        public TreeDropTarget(JTree tree)
 +
        {
 +
            this.targetTree = tree;
 +
            this.target = new DropTarget(this.targetTree, this);
 +
        }
 +
 +
        public void dragEnter(DropTargetDragEvent event)
 +
        {
 +
            event.acceptDrag(event.getDropAction());
 +
        }
 +
 +
        public void dragOver(DropTargetDragEvent event)
 +
        {
 +
        }
 +
 +
        public void dragExit(DropTargetEvent event)
 +
        {
 +
        }
 +
 +
        public void dropActionChanged(DropTargetDragEvent event)
 +
        {
 +
        }
 +
 +
        public void drop(DropTargetDropEvent event)
 +
        {
 +
            Point point = event.getLocation();
 +
            JTree tree = (JTree)event.getDropTargetContext().getComponent();
 +
            TreePath parentPath = tree.getClosestPathForLocation(point.x, point.y);
 +
            if (parentPath != null)
 +
            {
 +
                try
 +
                {
 +
                    Transferable transferable = event.getTransferable();
 +
                    DataFlavor[] flavors = transferable.getTransferDataFlavors();
 +
                    for (DataFlavor flavor : flavors) {
 +
                        if (transferable.isDataFlavorSupported(flavor)) {
 +
                            DefaultMutableTreeNode parent = (DefaultMutableTreeNode) parentPath.getLastPathComponent();
 +
                            ServiceLabelItem parentServiceLabelItem = (ServiceLabelItem) parent.getUserObject();
 +
 +
                            ServiceLabelItem serviceLabelItem = (ServiceLabelItem) transferable.getTransferData(flavor);
 +
                            if (parentServiceLabelItem.getId() == serviceLabelItem.getId()) {
 +
                                break;
 +
                            }
 +
 +
                            serviceLabelItem.setParentId(parentServiceLabelItem.getId());
 +
 +
                            event.acceptDrop(event.getDropAction());
 +
 +
                            DefaultMutableTreeNode newServiceLabelTreeNode = new DefaultMutableTreeNode();
 +
                            newServiceLabelTreeNode.setUserObject(serviceLabelItem);
 +
 +
                            DefaultTreeModel defaultTreeModel = (DefaultTreeModel) tree.getModel();
 +
                            defaultTreeModel.insertNodeInto(newServiceLabelTreeNode, parent, parent.getChildCount());
 +
                            try
 +
                            {
 +
                                ServiceLabelModulePanel.this.getContext().getPort(ServiceLabelService.class).updateServiceLabelTreeItem(serviceLabelItem);
 +
                            }
 +
                            catch (BGException ex)
 +
                            {
 +
                                ServiceLabelModulePanel.this.processException(ex);
 +
                            }
 +
                            tree.expandPath(new TreePath(parent.getPath()));
 +
                            tree.scrollPathToVisible(new TreePath(parent.getPath()));
 +
                            event.dropComplete(true);
 +
                            return;
 +
                        }
 +
                    }
 +
                    event.rejectDrop();
 +
                }
 +
                catch (Exception e)
 +
                {
 +
                    e.printStackTrace();
 +
                    event.rejectDrop();
 +
                }
 +
            }
 +
            else
 +
            {
 +
                event.rejectDrop();
 +
            }
 +
        }
 +
    }
 +
 +
    private class ServiceTreeCellEditor implements TreeCellEditor
 +
    {
 +
        private Object editValue;
 +
 +
        public boolean stopCellEditing()
 +
        {
 +
            return true;
 +
        }
 +
 +
        public boolean shouldSelectCell(EventObject anEvent)
 +
        {
 +
            return false;
 +
        }
 +
 +
        public void removeCellEditorListener(CellEditorListener l)
 +
        {
 +
        }
 +
 +
        public boolean isCellEditable(EventObject anEvent)
 +
        {
 +
            boolean result = anEvent == null;
 +
            if (!result)
 +
            {
 +
                ServiceLabelTree tree = (ServiceLabelTree)anEvent.getSource();
 +
                if ((anEvent instanceof MouseEvent))
 +
                {
 +
                    MouseEvent mouseEvent = (MouseEvent)anEvent;
 +
                    TreePath treePath = tree.getPathForLocation(mouseEvent.getX(), mouseEvent.getY());
 +
                    if(treePath!=null){
 +
                        Object selectedObject = treePath.getLastPathComponent();
 +
                        if ((selectedObject instanceof DefaultMutableTreeNode))
 +
                        {
 +
                            DefaultMutableTreeNode serviceLabelTreeNode = (DefaultMutableTreeNode)selectedObject;
 +
                            if (serviceLabelTreeNode.isRoot())
 +
                            {
 +
                                result = false;
 +
                            }
 +
                        }
 +
                    }
 +
                }
 +
            }
 +
            return result;
 +
        }
 +
 +
        public Object getCellEditorValue()
 +
        {
 +
            return this.editValue;
 +
        }
 +
 +
        public void cancelCellEditing()
 +
        {
 +
        }
 +
 +
        public void addCellEditorListener(CellEditorListener l)
 +
        {
 +
        }
 +
 +
        public Component getTreeCellEditorComponent(final JTree tree, Object value, boolean isSelected, boolean expanded, boolean leaf, int row) {
 +
            final JTextField comp = new JTextField();
 +
 +
            comp.addKeyListener(new KeyAdapter()
 +
            {
 +
                public void keyReleased(KeyEvent keyEvent)
 +
                {
 +
                    if (keyEvent.getKeyCode() == 10)
 +
                    {
 +
                        ServiceLabelItem tariffLabelItem = (ServiceLabelItem)ServiceTreeCellEditor.this.editValue;
 +
                        tariffLabelItem.setTitle(comp.getText());
 +
                        try
 +
                        {
 +
                            (ServiceLabelModulePanel.this.getContext().getPort(ServiceLabelService.class)).updateServiceLabelTreeItem(tariffLabelItem);
 +
                        }
 +
                        catch (BGException ex)
 +
                        {
 +
                            ServiceLabelModulePanel.this.processException(ex);
 +
                        }
 +
                        tree.stopEditing();
 +
                        ServiceLabelModulePanel.this.setLabelTreeData(ServiceLabelModulePanel.this.filterLabelTree, -1);
 +
                    }
 +
                }
 +
            });
 +
            if ((value instanceof DefaultMutableTreeNode))
 +
            {
 +
                this.editValue = ((DefaultMutableTreeNode)value).getUserObject();
 +
                comp.setText(this.editValue.toString());
 +
                comp.setBorder(BorderFactory.createLineBorder(Color.gray, 1));
 +
            }
 +
 +
            comp.repaint();
 +
 +
            return row > 0 ? comp : null;
 +
        }
 +
    }
 +
 +
    class ModeButton extends JToggleButton
 +
    {
 +
        ModeButton(String actionCommand, ButtonGroup buttonGroup, ActionListener actionListener, String toolTipText)
 +
        {
 +
            setMargin(new Insets(0, 0, 0, 0));
 +
            setPreferredSize(new Dimension(20, 16));
 +
            setToolTipText(toolTipText);
 +
            buttonGroup.add(this);
 +
            addActionListener(actionListener);
 +
            setActionCommand(actionCommand);
 +
            setText(String.valueOf(toolTipText.charAt(0)));
 +
        }
 +
    }
 +
}
 +
</source>
 +
 +
Контрол дерева меток:
 +
<source lang=java>
 +
package ru.dsi.bgbilling.kernel.module.client;
 +
 +
import ru.dsi.bgbilling.kernel.module.common.bean.ServiceLabelItem;
 +
import ru.dsi.bgbilling.kernel.module.common.bean.ServiceLabelTreeCellRenderer;
 +
 +
import javax.swing.*;
 +
import javax.swing.tree.DefaultMutableTreeNode;
 +
import javax.swing.tree.DefaultTreeModel;
 +
import javax.swing.tree.TreePath;
 +
import javax.swing.tree.TreeSelectionModel;
 +
import java.awt.*;
 +
import java.awt.dnd.Autoscroll;
 +
import java.awt.event.*;
 +
import java.util.ArrayList;
 +
import java.util.List;
 +
 +
public class ServiceLabelTree extends JTree
 +
        implements Autoscroll
 +
{
 +
    private int margin = 12;
 +
    private NodeSelectionListener listener = new NodeSelectionListener();
 +
 +
    public ServiceLabelTree()
 +
    {
 +
        setBorder(BorderFactory.createEmptyBorder(3, 3, 3, 3));
 +
        setCellRenderer(new ServiceLabelTreeCellRenderer());
 +
        setRootVisible(true);
 +
        setShowsRootHandles(true);
 +
        getSelectionModel().setSelectionMode(TreeSelectionModel.SINGLE_TREE_SELECTION);
 +
        onNodeSelectionListener();
 +
    }
 +
 +
    public void setData(List<ServiceLabelItem> serviceLabelItemList)
 +
    {
 +
        ServiceLabelItem root = new ServiceLabelItem();
 +
        root.setTitle("Корневой эелемент");
 +
        setModel(new DefaultTreeModel(new DefaultMutableTreeNode(root)));
 +
        buildServiceLabelTree((DefaultMutableTreeNode) getModel().getRoot(), serviceLabelItemList, 0);
 +
 +
        DefaultMutableTreeNode node = ((DefaultMutableTreeNode)getModel().getRoot()).getNextNode();
 +
        while (node != null)
 +
        {
 +
            expandPath(new TreePath(node.getPath()));
 +
            node = node.getNextNode();
 +
        }
 +
    }
 +
 +
    public List<ServiceLabelItem> getSelectedItems()
 +
    {
 +
        List<ServiceLabelItem> serviceLabelItemList = new ArrayList<ServiceLabelItem>();
 +
        DefaultMutableTreeNode node = ((DefaultMutableTreeNode)getModel().getRoot()).getNextNode();
 +
        while (node != null)
 +
        {
 +
            Object userObject = node.getUserObject();
 +
            if (((userObject instanceof ServiceLabelItem)) && (((ServiceLabelItem)userObject).isSelected()))
 +
            {
 +
                serviceLabelItemList.add((ServiceLabelItem)userObject);
 +
            }
 +
            node = node.getNextNode();
 +
        }
 +
        return serviceLabelItemList;
 +
    }
 +
 +
    public List<Integer> getSelectedIds()
 +
    {
 +
        List<Integer> ids = new ArrayList<Integer>();
 +
        DefaultMutableTreeNode node = ((DefaultMutableTreeNode)getModel().getRoot()).getNextNode();
 +
        while (node != null)
 +
        {
 +
            Object userObject = node.getUserObject();
 +
            if (((userObject instanceof ServiceLabelItem)) && (((ServiceLabelItem)userObject).isSelected()))
 +
            {
 +
                ids.add(((ServiceLabelItem)userObject).getId());
 +
            }
 +
            node = node.getNextNode();
 +
        }
 +
        return ids;
 +
    }
 +
 +
    private void buildServiceLabelTree(DefaultMutableTreeNode currentNode, List<ServiceLabelItem> serviceLabelItemList, int parentId)
 +
    {
 +
        for (ServiceLabelItem serviceLabelItem : serviceLabelItemList)
 +
        {
 +
            if (serviceLabelItem.getParentId() == parentId)
 +
            {
 +
                DefaultMutableTreeNode labelTreeNode = new DefaultMutableTreeNode();
 +
                labelTreeNode.setUserObject(serviceLabelItem);
 +
                currentNode.add(labelTreeNode);
 +
                buildServiceLabelTree(labelTreeNode, serviceLabelItemList, serviceLabelItem.getId());
 +
            }
 +
        }
 +
    }
 +
 +
    public String convertValueToText(Object value, boolean selected, boolean expanded, boolean leaf, int row, boolean hasFocus)
 +
    {
 +
        String text = super.convertValueToText(value, selected, expanded, leaf, row, hasFocus);
 +
        if (((value instanceof DefaultMutableTreeNode)) && (!isEditable()))
 +
        {
 +
            DefaultMutableTreeNode servicefLabelTreeNode = (DefaultMutableTreeNode)value;
 +
            Object userObject = servicefLabelTreeNode.getUserObject();
 +
            if ((userObject instanceof ServiceLabelItem))
 +
            {
 +
                ServiceLabelItem serviceLabelItem = (ServiceLabelItem)userObject;
 +
                if (serviceLabelItem.getServiceLinkCount() > 0)
 +
                {
 +
                    text = text.concat(" [").concat(String.valueOf(serviceLabelItem.getServiceLinkCount())).concat("]");
 +
                }
 +
            }
 +
        }
 +
        return text;
 +
    }
 +
 +
    public void onNodeSelectionListener()
 +
    {
 +
        boolean fl = true;
 +
        for (MouseListener mouseListener : getMouseListeners())
 +
        {
 +
            if (mouseListener == this.listener)
 +
            {
 +
                fl = false;
 +
                break;
 +
            }
 +
        }
 +
        if (fl) addMouseListener(this.listener);
 +
 +
        fl = true;
 +
        for (KeyListener keyListener : getKeyListeners())
 +
        {
 +
            if (keyListener == this.listener)
 +
            {
 +
                fl = false;
 +
                break;
 +
            }
 +
        }
 +
        if (fl) addKeyListener(this.listener);
 +
    }
 +
 +
    public void offNodeSelectionListener()
 +
    {
 +
        removeMouseListener(this.listener);
 +
        removeKeyListener(this.listener);
 +
    }
 +
 +
    public Insets getAutoscrollInsets()
 +
    {
 +
        Rectangle outer = getBounds();
 +
        Rectangle inner = getParent().getBounds();
 +
        return new Insets(inner.y - outer.y + this.margin, inner.x - outer.x + this.margin, outer.height - inner.height - inner.y + outer.y + this.margin, outer.width - inner.width - inner.x + outer.x + this.margin);
 +
    }
 +
 +
    public void autoscroll(Point p)
 +
    {
 +
        int realrow = getRowForLocation(p.x, p.y);
 +
        Rectangle outer = getBounds();
 +
        realrow = realrow < getRowCount() - 1 ? realrow + 1 : p.y + outer.y <= this.margin ? realrow - 1 : realrow < 1 ? 0 : realrow;
 +
        scrollRowToVisible(realrow);
 +
    }
 +
 +
    private final class NodeSelectionListener extends MouseAdapter
 +
            implements KeyListener
 +
    {
 +
        private NodeSelectionListener()
 +
        {
 +
        }
 +
 +
        public void mouseReleased(MouseEvent e)
 +
        {
 +
            int x = e.getX();
 +
            int y = e.getY();
 +
            int row = ServiceLabelTree.this.getRowForLocation(x, y);
 +
            TreePath path = ServiceLabelTree.this.getPathForRow(row);
 +
            if (path != null)
 +
            {
 +
                if (SwingUtilities.isLeftMouseButton(e))
 +
                {
 +
                    Object selectedObject = ServiceLabelTree.this.getLastSelectedPathComponent();
 +
                    if ((selectedObject instanceof DefaultMutableTreeNode)) action((DefaultMutableTreeNode)selectedObject);
 +
                }
 +
            }
 +
        }
 +
 +
        public final void keyReleased(KeyEvent keyevent)
 +
        {
 +
            int i;
 +
            if (((i = keyevent.getKeyCode()) == 32) || (i == 10))
 +
            {
 +
                action((DefaultMutableTreeNode)ServiceLabelTree.this.getLastSelectedPathComponent());
 +
            }
 +
        }
 +
 +
        public void keyPressed(KeyEvent e)
 +
        {
 +
        }
 +
 +
        public void keyTyped(KeyEvent e)
 +
        {
 +
        }
 +
 +
        private void action(DefaultMutableTreeNode node)
 +
        {
 +
            if (node == null)
 +
            {
 +
                return;
 +
            }
 +
 +
            Object userObject = node.getUserObject();
 +
            if ((userObject instanceof ServiceLabelItem))
 +
            {
 +
                ServiceLabelItem serviceLabelItem = (ServiceLabelItem)userObject;
 +
                serviceLabelItem.setSelected(!serviceLabelItem.isSelected());
 +
                ServiceLabelTree.this.firePropertyChange("changeSelected", !serviceLabelItem.isSelected(), serviceLabelItem.isSelected());
 +
                ServiceLabelTree.this.repaint();
 +
            }
 +
        }
 +
    }
 +
}
</source>
</source>

Текущая версия на 08:23, 21 апреля 2013

Содержание

Описание

Для отчётов полезно иметь группировку услуг по типам вне зависимости от модуля. Например, группа услуг "Интернет" - туда могут входить как услуги трафиков модулей Inet, Dialup, IPN, так и абонплаты за интернет. Аналогично, "VPN"

Было решено сделать группировку аналогично меткам тарифов - в виде дерева меток.

Решение состоит из серверного API и клиентского интерфейса. Решение является упрощённой копипастой стандартной работы с метками тарифов.

Файл:service_labels_1.png

Общие классы

Классы, которые должны быть как в серверных библиотеках, так и в клиентских

Во-первых, нам понадобится веб-сервис для работы с метками тарифов:

package ru.bitel.bgbilling.kernel.module.common.service;
 
import ru.bitel.bgbilling.common.BGException;
import ru.dsi.bgbilling.kernel.module.common.bean.ServiceItem;
import ru.dsi.bgbilling.kernel.module.common.bean.ServiceLabelItem;
 
import javax.jws.WebMethod;
import javax.jws.WebParam;
import javax.jws.WebService;
import java.util.List;
import java.util.Set;
 
@WebService
public abstract interface ServiceLabelService
{
    @WebMethod
    public abstract List<ServiceLabelItem> getServiceLabelTreeItemList(@WebParam(name="serviceId") int serviceId)
            throws BGException;
 
    @WebMethod
    public abstract void setServiceLabelTreeItemList(@WebParam(name="serviceId") int serviceId, @WebParam(name="items") List<ServiceLabelItem> items)
            throws BGException;
 
    @WebMethod
    public abstract int updateServiceLabelTreeItem(@WebParam(name="serviceLabelItem") ServiceLabelItem serviceLabelItem)
            throws BGException;
 
    @WebMethod
    public abstract void removeServiceLabelTreeItem(@WebParam(name="serviceLabelItemId") int serviceLabelItemId)
            throws BGException;
 
    @WebMethod
    public abstract List<ServiceItem> getServiceList(@WebParam(name="moduleIds") Set<Integer> moduleIds,
                                                     @WebParam(name="serviceLabelIds") List<Integer> serviceLabelIds)
            throws BGException;
}

Элемент списка услуг для отображения:

package ru.dsi.bgbilling.kernel.module.common.bean;
 
import ru.bitel.common.model.IdTitle;
 
import javax.xml.bind.annotation.XmlAttribute;
 
/**
 * Услуга, расширенная доп информацией
 */
public class ServiceItem extends IdTitle{
    private int labelCount;
    private String moduleTitle;
    private int moduleId;
    private boolean using;
 
    @XmlAttribute
    public int getLabelCount() {
        return labelCount;
    }
 
    public void setLabelCount(int labelCount) {
        this.labelCount = labelCount;
    }
 
    @XmlAttribute
    public String getModuleTitle() {
        return moduleTitle;
    }
 
    public void setModuleTitle(String moduleTitle) {
        this.moduleTitle = moduleTitle;
    }
 
    @XmlAttribute
    public int getModuleId()
    {
        return this.moduleId;
    }
 
    public void setModuleId(int moduleId)
    {
        this.moduleId = moduleId;
    }
 
    @XmlAttribute
    public boolean isUsing()
    {
        return this.using;
    }
 
    public void setUsing(boolean used)
    {
        this.using = used;
    }
}

Элемент дерева меток:

package ru.dsi.bgbilling.kernel.module.common.bean;
 
import ru.bitel.common.model.IdTitle;
 
import javax.xml.bind.annotation.XmlAttribute;
 
public class ServiceLabelItem extends IdTitle
{
    private int parentId = -1;
    private int serviceLinkCount = 0;
    private boolean selected = false;
 
    @XmlAttribute
    public int getParentId()
    {
        return this.parentId;
    }
 
    public void setParentId(int parentId)
    {
        this.parentId = parentId;
    }
 
    @XmlAttribute
    public int getServiceLinkCount()
    {
        return this.serviceLinkCount;
    }
 
    public void setServiceLinkCount(int serviceLinkCount)
    {
        this.serviceLinkCount = serviceLinkCount;
    }
 
    @XmlAttribute
    public boolean isSelected()
    {
        return this.selected;
    }
 
    public void setSelected(boolean selected)
    {
        this.selected = selected;
    }
}

Renderer дерева меток:

package ru.dsi.bgbilling.kernel.module.common.bean;
 
import ru.bitel.bgbilling.client.util.ClientUtils;
 
import javax.swing.*;
import javax.swing.tree.DefaultMutableTreeNode;
import javax.swing.tree.DefaultTreeCellRenderer;
import javax.swing.tree.TreeCellRenderer;
import java.awt.*;
 
public class ServiceLabelTreeCellRenderer extends JPanel
        implements TreeCellRenderer
{
    private JCheckBox check;
    private DefaultTreeCellRenderer label;
 
    public ServiceLabelTreeCellRenderer()
    {
        setLayout(new GridBagLayout());
        add(this.check = new JCheckBox(), new GridBagConstraints(0, 0, 1, 1, 0.0D, 0.0D, 17, 0, new Insets(0, 0, 0, 0), 0, 0));
        add(this.label = new DefaultTreeCellRenderer(), new GridBagConstraints(1, 0, 1, 1, 0.0D, 0.0D, 17, 0, new Insets(0, 0, 0, 0), 0, 0));
        prepare();
        setOpaque(false);
        this.label.setOpenIcon(ClientUtils.getIcon("node.png"));
        this.label.setClosedIcon(ClientUtils.getIcon("node.png"));
        this.label.setLeafIcon(ClientUtils.getIcon("leaf.png"));
    }
 
    public void setEnabled(boolean enabled)
    {
        super.setEnabled(enabled);
        this.check.setEnabled(enabled);
    }
 
    public Component getTreeCellRendererComponent(JTree tree, Object value, boolean selected, boolean expanded, boolean leaf, int row, boolean hasFocus)
    {
        prepare();
 
        this.label.getTreeCellRendererComponent(tree, value, selected, expanded, leaf, row, hasFocus);
 
        if ((value instanceof DefaultMutableTreeNode))
        {
            setEnabled(tree.isEnabled());
            this.check.setEnabled(true);
            DefaultMutableTreeNode serviceLabelTreeNode = (DefaultMutableTreeNode)value;
            Object userObject = serviceLabelTreeNode.getUserObject();
            if ((userObject instanceof ServiceLabelItem))
            {
                this.check.setSelected(((ServiceLabelItem)userObject).isSelected());
            }
            this.check.setVisible(!serviceLabelTreeNode.isRoot());
        }
        invalidate();
        return this;
    }
 
    public final DefaultTreeCellRenderer getTreeCellRenderer()
    {
        return this.label;
    }
 
    private void prepare()
    {
        Color bColor = UIManager.getColor("Tree.textBackground");
        setBackground(bColor);
        this.check.setBackground(bColor);
        this.label.setBackgroundNonSelectionColor(bColor);
        this.label.setBackgroundSelectionColor(bColor);
        this.label.setBackground(bColor);
    }
}


Сервер

Таблицы mysql

Таблицы аналогичны таблицам меток тарифов tariff_label и tariff_label_link

CREATE TABLE `custom_service_label` (
  `id` int(11) NOT NULL AUTO_INCREMENT,
  `parent_id` int(11) NOT NULL DEFAULT '0',
  `title` varchar(255) NOT NULL DEFAULT '',
  PRIMARY KEY (`id`)
)
 
CREATE TABLE `custom_service_label_link` (
  `sid` int(11) NOT NULL DEFAULT '0',
  `label_id` int(11) NOT NULL DEFAULT '0',
  KEY `sid` (`sid`,`label_id`)
)

Классы java

Реализация веб-сервиса меток услуг

package ru.bitel.bgbilling.kernel.module.server.service;
 
import ru.bitel.bgbilling.common.BGException;
import ru.bitel.bgbilling.kernel.container.service.server.AbstractService;
import ru.bitel.bgbilling.kernel.module.common.bean.BGModule;
import ru.bitel.bgbilling.kernel.module.common.bean.Service;
import ru.bitel.bgbilling.kernel.module.common.service.ServiceLabelService;
import ru.bitel.bgbilling.kernel.module.server.bean.ModuleManager;
import ru.bitel.bgbilling.kernel.module.server.bean.ServiceManager;
import ru.dsi.bgbilling.kernel.module.common.bean.ServiceItem;
import ru.dsi.bgbilling.kernel.module.common.bean.ServiceLabelItem;
import ru.dsi.bgbilling.kernel.module.server.bean.ServiceLabelDao;
 
import javax.jws.WebParam;
import javax.jws.WebService;
import java.sql.Connection;
import java.util.*;
 
/**
 * Вебсервис для работы с метками (группами) услуг
 */
@WebService(endpointInterface="ru.bitel.bgbilling.kernel.module.common.service.ServiceLabelService")
public class ServiceLabelServiceImpl extends AbstractService
        implements ServiceLabelService {
    @Override
    public List<ServiceLabelItem> getServiceLabelTreeItemList(@WebParam(name="serviceId") int serviceId) throws BGException {
        ServiceLabelDao serviceLabelManager = new ServiceLabelDao(getConnection());
        List<ServiceLabelItem> serviceLabelItems = serviceLabelManager.getServiceLabelItemList();
        if (serviceId > 0)
        {
            Set<Integer> serviceLabelSet = serviceLabelManager.getServiceLabelIds(serviceId);
            for (ServiceLabelItem serviceLabelItem : serviceLabelItems)
            {
                serviceLabelItem.setSelected(serviceLabelSet.contains(Integer.valueOf(serviceLabelItem.getId())));
            }
        }
        return serviceLabelItems;
    }
 
    @Override
    public void setServiceLabelTreeItemList(@WebParam(name="serviceId") int serviceId,
                                            @WebParam(name="items") List<ServiceLabelItem> items) throws BGException {
        Set<Integer> labelIds = new HashSet<Integer>();
        if (items != null)
        {
            for (ServiceLabelItem tariffLabelItem : items)
            {
                labelIds.add(tariffLabelItem.getId());
            }
        }
        new ServiceLabelDao(getConnection()).setServiceLabelIds(serviceId, labelIds);
    }
 
    @Override
    public int updateServiceLabelTreeItem(@WebParam(name = "serviceLabelItem") ServiceLabelItem serviceLabelItem) throws BGException {
        new ServiceLabelDao(getConnection()).updateServiceLabelTreeItem(serviceLabelItem);
        return serviceLabelItem != null ? serviceLabelItem.getId() : -1;
    }
 
    @Override
    public void removeServiceLabelTreeItem(@WebParam(name = "serviceLabelItemId") int serviceLabelItemId) throws BGException {
        new ServiceLabelDao(getConnection()).removeServiceLabelItem(serviceLabelItemId);
    }
 
    @Override
    public List<ServiceItem> getServiceList(@WebParam(name = "moduleIds") Set<Integer> moduleIds, @WebParam(name = "serviceLabelIds") List<Integer> serviceLabelIds) throws BGException {
        List<ServiceItem> result = new ArrayList<ServiceItem>();
        Connection con = getConnection();
        ServiceManager sm = new ServiceManager(con);
        ModuleManager mm = new ModuleManager(con);
        ServiceLabelDao slDao = new ServiceLabelDao(con);
        Map<Integer,BGModule> modulesMap = mm.getModulesMap();
        List<Service> services = sm.list();
        ServiceItem serviceItem;
        BGModule module;
        boolean found;
        for(Service service : services){
            if(moduleIds!=null && moduleIds.size()>0){
                if(!moduleIds.contains(service.getModuleId())){
                    continue;
                }
            }
            Set<Integer> labelIds = slDao.getServiceLabelIds(service.getId());
            if(serviceLabelIds!=null && serviceLabelIds.size()>0){
                found = false;//Ищем, есть ли у услуги хотя бы одна метка из фильтра serviceLabelIds
                for(Integer label_id : serviceLabelIds){
                    if(labelIds.contains(label_id)){
                        found = true;
                        break;
                    }
                }
                if(!found){
                    continue;
                }
            }
            //всё ок - добавляем услугу в список
            serviceItem = new ServiceItem();
            serviceItem.setId(service.getId());
            serviceItem.setTitle(service.getTitle());
            serviceItem.setModuleId(service.getModuleId());
            serviceItem.setUsing(service.isUsing());
            serviceItem.setLabelCount(labelIds.size());
            module = modulesMap.get(service.getModuleId());
            serviceItem.setModuleTitle(module == null ? "???" : module.getTitle());
            result.add(serviceItem);
        }
        sm.recycle();
        return result;
    }
 
}

Dao для работы с метками (группами) услуг:

package ru.dsi.bgbilling.kernel.module.server.bean;
 
import ru.bitel.bgbilling.common.BGException;
import ru.bitel.bgbilling.server.util.ServerUtils;
import ru.dsi.bgbilling.kernel.module.common.bean.ServiceLabelItem;
 
import java.sql.*;
import java.util.*;
 
/**
 * Dao для работы с метками (группами) услуг
 */
public class ServiceLabelDao {
    protected static final String TABLE_SERVICE_LABEL = "custom_service_label";
    protected static final String TABLE_SERVICE_LABEL_LINK = "custom_service_label_link";
    private Connection con;
 
    public ServiceLabelDao(Connection con)
    {
        this.con = con;
    }
 
    public List<ServiceLabelItem> getServiceLabelItemList()
            throws BGException
    {
        List<ServiceLabelItem> result = new ArrayList<ServiceLabelItem>();
        try
        {
            Map<Integer, ServiceLabelItem> map = new HashMap<Integer, ServiceLabelItem>();
 
            Statement st = this.con.createStatement();
 
            StringBuilder query =
                    new StringBuilder("SELECT * FROM ")
                            .append(TABLE_SERVICE_LABEL)
                            .append(" ORDER BY title");
            ResultSet rs = st.executeQuery(query.toString());
            while (rs.next())
            {
                ServiceLabelItem serviceLabelItem = getServiceLabelItemFromRS(rs);
                map.put(serviceLabelItem.getId(), serviceLabelItem);
                result.add(serviceLabelItem);
            }
            rs.close();
 
            query.setLength(0);
            query.append("SELECT label_id, count(*) FROM ").append(TABLE_SERVICE_LABEL_LINK).append(" GROUP BY label_id");
            rs = st.executeQuery(query.toString());
            while (rs.next())
            {
                ServiceLabelItem serviceLabelItem = map.get(rs.getInt(1));
                if (serviceLabelItem != null)
                {
                    serviceLabelItem.setServiceLinkCount(rs.getInt(2));
                }
            }
            rs.close();
 
            st.close();
        }
        catch (Exception ex)
        {
            throw new BGException(ex);
        }
        return result;
    }
 
    public Set<Integer> getServiceLabelIds(int serviceId)
            throws BGException
    {
        Set<Integer> result = new HashSet<Integer>();
        try
        {
            String query = "SELECT label_id FROM " + TABLE_SERVICE_LABEL_LINK + " WHERE sid=" + serviceId;
            Statement st = this.con.createStatement();
            ResultSet rs = st.executeQuery(query);
            while (rs.next())
            {
                result.add(rs.getInt(1));
            }
            rs.close();
            st.close();
        }
        catch (Exception ex)
        {
            throw new BGException(ex);
        }
        return result;
    }
 
    public void setServiceLabelIds(int serviceId, Set<Integer> labelIds)
            throws BGException
    {
        try
        {
            StringBuilder query = new StringBuilder("DELETE FROM ").append(TABLE_SERVICE_LABEL_LINK)
                    .append(" WHERE sid=").append(serviceId);
            Statement st = this.con.createStatement();
            st.executeUpdate(query.toString());
            st.close();
 
            query.setLength(0);
            query.append("INSERT INTO ").append(TABLE_SERVICE_LABEL_LINK).append(" SET sid=").append(serviceId).append(", label_id=?");
            PreparedStatement ps = this.con.prepareStatement(query.toString());
            for (Integer id : labelIds)
            {
                ps.setInt(1, id);
                ps.executeUpdate();
            }
            ps.close();
        }
        catch (Exception ex)
        {
            throw new BGException(ex);
        }
    }
 
    public void updateServiceLabelTreeItem(ServiceLabelItem serviceLabelItem)
            throws BGException
    {
        try
        {
            if (serviceLabelItem == null)
            {
                throw new NullPointerException("serviceLabelItem is null!");
            }
 
            StringBuilder query = new StringBuilder();
 
            if (serviceLabelItem.getId() > 0)
            {
                query.append("UPDATE ");
                query.append(TABLE_SERVICE_LABEL);
                query.append(" SET parent_id=?, title=? WHERE id=?");
            }
            else
            {
                query.append("INSERT INTO ");
                query.append(TABLE_SERVICE_LABEL);
                query.append(" SET parent_id=?, title=?");
            }
 
            PreparedStatement ps = this.con.prepareStatement(query.toString());
            ps.setInt(1, serviceLabelItem.getParentId());
            ps.setString(2, serviceLabelItem.getTitle());
 
            if (serviceLabelItem.getId() > 0)
            {
                ps.setInt(3, serviceLabelItem.getId());
            }
 
            ps.executeUpdate();
 
            if (serviceLabelItem.getId() < 0)
            {
                serviceLabelItem.setId(ServerUtils.lastInsertId(this.con));
            }
 
            ps.close();
        }
        catch (Exception ex)
        {
            throw new BGException(ex);
        }
    }
 
    public void removeServiceLabelItem(int serviceLabelItemId)
            throws BGException
    {
        try
        {
            Statement st = this.con.createStatement();
 
            StringBuilder query = new StringBuilder("DELETE FROM ").append(TABLE_SERVICE_LABEL_LINK)
                    .append(" WHERE label_id=").append(serviceLabelItemId);
            st.executeUpdate(query.toString());
 
            query.setLength(0);
            query.append("DELETE FROM ").append(TABLE_SERVICE_LABEL).append(" WHERE id=").append(serviceLabelItemId);
            st.executeUpdate(query.toString());
 
            st.close();
        }
        catch (Exception ex)
        {
            throw new BGException(ex);
        }
    }
 
    /*public List<ServiceItem> getServices(int moduleId, List<Integer> serviceLabelIds)
            throws BGException {
        try {
            StringBuilder sb = new StringBuilder("SELECT * FROM service s ").
                    append("left join module m on s.mid=m.id ").
                    append("left join " + TABLE_SERVICE_LABEL_LINK + " sll on s.id=sll.sid ").
                    append("WHERE 1 ");
            if(moduleId>0){
                sb.append("AND s.mid=").append(moduleId).append(" ");
            }
            if(serviceLabelIds!=null && serviceLabelIds.size()>0){
                sb.append("AND sll.label_id in (")
                        .append(Utils.toString(serviceLabelIds))
                        .append(") ");
            }
            sb.append("GROUP BY ")
 
            PreparedStatement ps = this.con.prepareStatement();
        } catch (SQLException e) {
            throw new BGException(e);
        }
 
        ServiceManager sm = new ServiceManager(this.con);
        List<Service> serviceList = sm.list(moduleId);
        for(Service service: serviceList){
            service.
        }
        sm.recycle();
    }*/
 
    private ServiceLabelItem getServiceLabelItemFromRS(ResultSet rs)
            throws SQLException
    {
        ServiceLabelItem serviceLabelItem = new ServiceLabelItem();
        serviceLabelItem.setId(rs.getInt("id"));
        serviceLabelItem.setParentId(rs.getInt("parent_id"));
        serviceLabelItem.setTitle(rs.getString("title"));
        return serviceLabelItem;
    }
}

Клиентские классы

В файл /bitel/billing/module/services/npay/setup_user.properties пропишем нашу панель как вкладку модуля абонплат с названием «Группы услуг»

module.tab.3.class=bitel.billing.module.services.npay.ServiceLabelModulePanel
module.tab.3.title=\u0413\u0440\u0443\u043F\u043F\u044B \u0443\u0441\u043B\u0443\u0433

Собственно панель:

package bitel.billing.module.services.npay;
 
import bitel.billing.module.common.BGControlPanelListSelect;
import bitel.billing.module.common.BGTextField;
import bitel.billing.module.common.BGTitleBorder;
import ru.bitel.bgbilling.client.common.BGSplitPane;
import ru.bitel.bgbilling.client.common.BGUPanel;
import ru.bitel.bgbilling.client.common.BGUTable;
import ru.bitel.bgbilling.client.util.ClientUtils;
import ru.bitel.bgbilling.common.BGException;
import ru.bitel.bgbilling.kernel.module.common.service.ModuleService;
import ru.bitel.bgbilling.kernel.module.common.service.ServiceLabelService;
import ru.bitel.common.client.BGUAction;
import ru.bitel.common.client.table.BGTableModel;
import ru.dsi.bgbilling.kernel.module.client.ServiceLabelTree;
import ru.dsi.bgbilling.kernel.module.common.bean.ServiceItem;
import ru.dsi.bgbilling.kernel.module.common.bean.ServiceLabelItem;
import ru.dsi.bgbilling.kernel.module.common.bean.ServiceLabelTreeCellRenderer;
 
import javax.swing.*;
import javax.swing.event.CellEditorListener;
import javax.swing.tree.*;
import java.awt.*;
import java.awt.datatransfer.DataFlavor;
import java.awt.datatransfer.Transferable;
import java.awt.datatransfer.UnsupportedFlavorException;
import java.awt.dnd.*;
import java.awt.event.*;
import java.beans.PropertyChangeEvent;
import java.beans.PropertyChangeListener;
import java.io.IOException;
import java.util.EventObject;
import java.util.HashSet;
import java.util.List;
 
/**
 * Панель для редактирования меток услуг.
 * Метки услуг - аналог меток тарифных планов, только для услуг (service).
 * Метки хранятся в таблицах custom_service_label и custom_service_label_link
 */
public class ServiceLabelModulePanel extends BGUPanel {
    private BGControlPanelListSelect serviceModuleList = new BGControlPanelListSelect();
    private JPanel labelModePanel = null;
    private CardLayout cardLayout1 = new CardLayout();
    private JPanel rightPanel = new JPanel(this.cardLayout1);
    private JPopupMenu popupFilterMenu = new JPopupMenu();
    private JPopupMenu popupEditorMenu = new JPopupMenu();
    private BGTextField name = new BGTextField();
    /**
     * Текущая выбранная для редактирования услуга
     */
    private int serviceId = 0;
    private String serviceTitle = "";
 
    //дерево меток в фильтре сервисов
    private ServiceLabelTree filterLabelTree = new ServiceLabelTree();
    //дерево меток в редакторе сервиса
    private ServiceLabelTree serviceLabelTree = new ServiceLabelTree();
    private ServiceLabelService wsServiceLabel = getContext().getPort(ServiceLabelService.class, 0);
    private ModuleService wsModule = getContext().getPort(ModuleService.class, 0);
 
    private BGTableModel<ServiceItem> serviceModel = new BGTableModel<ServiceItem>("service")
    {
        protected void initColumns()
        {
            addColumn("ID", 60, 60, 60, "id", true);
            addColumn("Название", "title", true);
            addColumn("Модуль", "moduleTitle", true);
            addColumn("Используется", -1, 50, 50, "using", true);
            addColumn("Меток", 150, 150, 150, "labelCount", true);
        }
    };
    private BGUTable serviceTable = new BGUTable(this.serviceModel);
 
    @Override
    protected void jbInit() throws Exception {
 
        this.filterLabelTree.addPropertyChangeListener(new PropertyChangeListener()
        {
            public void propertyChange(PropertyChangeEvent event)
            {
                if ("changeSelected".equals(event.getPropertyName()))
                {
                    ServiceLabelModulePanel.this.setData();
                }
            }
        });
 
        this.filterLabelTree.setCellEditor(new DefaultTreeCellEditor(this.filterLabelTree,
                new DefaultTreeCellRenderer()
                {
                }
                , new ServiceTreeCellEditor()));
 
        setLabelTreeData(this.filterLabelTree, -1);
 
        this.serviceTable.setSelectionMode(ListSelectionModel.SINGLE_SELECTION);
        this.serviceTable.addMouseListener(new MouseAdapter()
        {
            public void mouseClicked(MouseEvent event)
            {
                if ((SwingUtilities.isLeftMouseButton(event)) && (event.getClickCount() == 2) && (ServiceLabelModulePanel.this.serviceTable.isEnabled()))
                {
                    ServiceLabelModulePanel.this.initServiceId();
                    ServiceLabelModulePanel.this.showServiceEditor();
                }
            }
        });
 
        JButton commitButton = new JButton("Применить");
        commitButton.addActionListener(new ActionListener()
        {
            public void actionPerformed(ActionEvent e)
            {
                ServiceLabelModulePanel.this.updateService();
            }
        });
        JButton cancelButton = new JButton("Закрыть");
        cancelButton.addActionListener(new ActionListener()
        {
            public void actionPerformed(ActionEvent e)
            {
                ServiceLabelModulePanel.this.setData();
            }
        });
 
        JPanel namePanel = new JPanel(new GridBagLayout());
        namePanel.setBorder(new BGTitleBorder(" Услуга "));
        this.name.setEditable(false);//Имя услуги просто отображаем - редактировать нельзя
        namePanel.add(this.name, new GridBagConstraints(0, 0, 1, 1, 1.0D, 0.0D, 10, 1, new Insets(0, 5, 5, 5), 0, 0));
 
        JPanel commitPanel = new JPanel(new GridBagLayout());
        commitPanel.add(Box.createHorizontalGlue(), new GridBagConstraints(0, 0, 1, 1, 1.0D, 0.0D, 13, 1, new Insets(5, 0, 5, 5), 0, 0));
        commitPanel.add(commitButton, new GridBagConstraints(1, 0, 1, 1, 0.0D, 0.0D, 13, 0, new Insets(5, 5, 5, 5), 0, 0));
        commitPanel.add(cancelButton, new GridBagConstraints(2, 0, 1, 1, 0.0D, 0.0D, 13, 0, new Insets(5, 5, 5, 5), 0, 0));
 
        JPanel labelPanel = new JPanel(new GridBagLayout());
        labelPanel.setBorder(new BGTitleBorder(" Метки "));
        labelPanel.add(new JScrollPane(this.serviceLabelTree), new GridBagConstraints(0, 0, 1, 1, 1.0D, 1.0D, 10, 1, new Insets(0, 5, 5, 5), 0, 0));
 
        JPanel preferencesPanel = new JPanel(new GridBagLayout());
        preferencesPanel.add(namePanel, new GridBagConstraints(0, 0, 2, 1, 1.0D, 0.0D, 10, 1, new Insets(0, 5, 5, 5), 0, 0));
        preferencesPanel.add(labelPanel, new GridBagConstraints(0, 1, 1, 1, 1.0D, 1.0D, 10, 1, new Insets(0, 5, 5, 5), 0, 0));
        preferencesPanel.add(commitPanel, new GridBagConstraints(0, 2, 2, 1, 1.0D, 0.0D, 10, 2, new Insets(0, 5, 5, 5), 0, 0));
 
        this.rightPanel.add(preferencesPanel, "editor");
        this.rightPanel.add(getServiceListPanel(), "list");
 
        setLayout(new GridBagLayout());
        add(new BGSplitPane(1, getFilterPanel(), this.rightPanel), new GridBagConstraints(0, 0, 1, 1, 1.0D, 1.0D, 10, 1, new Insets(0, 0, 0, 0), 0, 0));
 
        new TreeDragSource(this.filterLabelTree, 2);
        new TreeDropTarget(this.filterLabelTree);
        setData();
    }
 
    private void setData() {
        try {
            this.serviceModel.setData(this.wsServiceLabel.getServiceList(new HashSet<Integer>(
                    this.serviceModuleList.getListIds()),
                    this.filterLabelTree.getSelectedIds()));
            if (this.serviceModuleList.getList().getModel().getSize() == 0){
                ClientUtils.buildList(this.serviceModuleList.getList(), this.wsModule.moduleList());
            }
        } catch (BGException ex) {
            this.processException(ex);
        }
 
        showServiceTable();
    }
 
    private TreePath getSelectionPath(ServiceLabelTree filterLabelTree, String message)
    {
        TreePath treePath = filterLabelTree.getSelectionPath();
        if (treePath == null)
        {
            JOptionPane.showMessageDialog(this, message, "Сообщение об ошибке", JOptionPane.ERROR_MESSAGE);
        }
        return treePath;
    }
 
    private void updateService(){
        try{
            this.wsServiceLabel.setServiceLabelTreeItemList(this.serviceId, this.serviceLabelTree.getSelectedItems());
            updateFilterLabelTreeData(this.wsServiceLabel.getServiceLabelTreeItemList(-1));
        }catch (BGException ex){
            processException(ex);
        }
    }
 
    private void setLabelTreeData(ServiceLabelTree labelTree, int serviceId)
    {
        try
        {
            labelTree.setData(getContext().getPort(ServiceLabelService.class).getServiceLabelTreeItemList(serviceId));
        }
        catch (BGException ex)
        {
            processException(ex);
        }
    }
 
    private void updateFilterLabelTreeData(List<ServiceLabelItem> items)
    {
        DefaultTreeModel model = (DefaultTreeModel)this.filterLabelTree.getModel();
        for (ServiceLabelItem serviceLabelItem : items)
        {
            DefaultMutableTreeNode serviceLabelTreeNode = (DefaultMutableTreeNode)model.getRoot();
            while (serviceLabelTreeNode != null)
            {
                Object object = serviceLabelTreeNode.getUserObject();
                if ((object instanceof ServiceLabelItem))
                {
                    ServiceLabelItem item = (ServiceLabelItem)object;
                    if (item.getId() == serviceLabelItem.getId())
                    {
                        item.setTitle(serviceLabelItem.getTitle());
                        item.setServiceLinkCount(serviceLabelItem.getServiceLinkCount());
                        model.nodeChanged(serviceLabelTreeNode);
                        break;
                    }
                }
                serviceLabelTreeNode = serviceLabelTreeNode.getNextNode();
            }
        }
    }
 
    private void initServiceId()
    {
        this.serviceId = this.serviceModel.getSelectedRow().getId();
        this.serviceTitle = this.serviceModel.getSelectedRow().getTitle();
 
    }
 
    private void showServiceEditor()
    {
        setFilterServiceEnabled(false);
        this.serviceLabelTree.setComponentPopupMenu(this.popupFilterMenu);
        this.filterLabelTree.setComponentPopupMenu(null);
        this.cardLayout1.show(this.rightPanel, "editor");
        setServiceData();
    }
 
    private void showServiceTable()
    {
        setFilterServiceEnabled(true);
        this.serviceLabelTree.setComponentPopupMenu(null);
        this.filterLabelTree.setComponentPopupMenu(this.popupFilterMenu);
        this.cardLayout1.show(this.rightPanel, "list");
    }
 
    private void setFilterServiceEnabled(boolean enabled)
    {
        this.filterLabelTree.setEnabled(enabled);
        this.serviceModuleList.setEnabled(enabled);
        this.labelModePanel.setEnabled(enabled);
    }
 
    public void setServiceData()
    {
        if (this.serviceId < 1)
        {
            return;
        }
 
        this.name.setText(this.serviceTitle);
        //this.serviceId = Utils.parseInt(XMLUtils.getAttribute(plan, "id", "-1"));
        //this.serviceTitle.setText(XMLUtils.getAttribute(plan, "title", "Без названия ;-(("));
 
        setLabelTreeData(this.serviceLabelTree, this.serviceId);
    }
 
    private JPanel getServiceListPanel()
    {
        JPanel panel = new JPanel(new GridBagLayout());
        panel.setBorder(new BGTitleBorder(" Услуги "));
        panel.add(new JScrollPane(this.serviceTable), new GridBagConstraints(0, 0, 3, 1, 1.0D, 1.0D, 10, 1, new Insets(0, 5, 5, 5), 0, 0));
        return panel;
    }
 
    private JPanel getFilterPanel()
    {
        this.filterLabelTree.setComponentPopupMenu(this.popupFilterMenu);
        this.popupEditorMenu.add(new JMenuItem(new BGUAction("addServiceLabel", "Добавить метку")
        {
            public void actionPerformed(ActionEvent e)
            {
                TreePath treePath = ServiceLabelModulePanel.this.getSelectionPath(ServiceLabelModulePanel.this.filterLabelTree, "Выберите родительскую метку.");
                if (treePath != null)
                {
                    Object selectedObject = treePath.getLastPathComponent();
                    if ((selectedObject instanceof DefaultMutableTreeNode))
                    {
                        DefaultMutableTreeNode tariffLabelTreeNode = (DefaultMutableTreeNode)selectedObject;
                        Object userObject = tariffLabelTreeNode.getUserObject();
                        if ((userObject instanceof ServiceLabelItem))
                        {
                            ServiceLabelItem newServiceLabelItem = new ServiceLabelItem();
                            newServiceLabelItem.setId(-1);
                            newServiceLabelItem.setParentId(((ServiceLabelItem) userObject).getId());
                            newServiceLabelItem.setTitle("Новая метка");
 
                            DefaultMutableTreeNode newTariffLabelTreeNode = new DefaultMutableTreeNode();
                            newTariffLabelTreeNode.setUserObject(newServiceLabelItem);
 
                            DefaultTreeModel defaultTreeModel = (DefaultTreeModel)ServiceLabelModulePanel.this.filterLabelTree.getModel();
                            defaultTreeModel.insertNodeInto(newTariffLabelTreeNode, tariffLabelTreeNode, tariffLabelTreeNode.getChildCount());
                            ServiceLabelModulePanel.this.filterLabelTree.expandPath(new TreePath(tariffLabelTreeNode.getPath()));
                            ServiceLabelModulePanel.this.filterLabelTree.scrollPathToVisible(new TreePath(tariffLabelTreeNode.getPath()));
                            try
                            {
                                newServiceLabelItem.setId(ServiceLabelModulePanel.this.getContext().getPort(ServiceLabelService.class).updateServiceLabelTreeItem(newServiceLabelItem));
                            }
                            catch (BGException ex)
                            {
                                ServiceLabelModulePanel.this.processException(ex);
                            }
                        }
                    }
                }
            }
        }));
 
        this.popupEditorMenu.add(new JMenuItem(new BGUAction("renameServiceLabel", "Переименовать метку")
        {
            public void actionPerformed(ActionEvent e)
            {
                TreePath treePath = ServiceLabelModulePanel.this.getSelectionPath(ServiceLabelModulePanel.this.filterLabelTree, "Выберите метку");
                if (treePath != null)
                {
                    ServiceLabelModulePanel.this.filterLabelTree.startEditingAtPath(treePath);
                }
            }
        }));
        this.popupEditorMenu.add(new JMenuItem(new BGUAction("dropTarifLabel", "Удалить метку")
        {
            public void actionPerformed(ActionEvent e)
            {
                TreePath treePath = ServiceLabelModulePanel.this.getSelectionPath(ServiceLabelModulePanel.this.filterLabelTree, "Выберите метку");
                if (treePath != null)
                {
                    Object selectedObject = treePath.getLastPathComponent();
                    if ((selectedObject instanceof DefaultMutableTreeNode))
                    {
                        DefaultMutableTreeNode serviceLabelTreeNode = (DefaultMutableTreeNode)selectedObject;
                        if (serviceLabelTreeNode.isRoot())
                        {
                            JOptionPane.showMessageDialog(ServiceLabelModulePanel.this, "Корневой элемент удалить нельзя.", "Сообщение об ошибке", JOptionPane.ERROR_MESSAGE);
                        }
                        else if (!serviceLabelTreeNode.isLeaf())
                        {
                            JOptionPane.showMessageDialog(ServiceLabelModulePanel.this, "Удалить нельзя, т.к. метка содержит дочерние метки, удалите сначала их.", "Сообщение об ошибке", JOptionPane.ERROR_MESSAGE);
                        }
                        else
                        {
                            Object userObject = serviceLabelTreeNode.getUserObject();
                            if ((userObject instanceof ServiceLabelItem))
                            {
                                boolean removeFlag = true;
                                ServiceLabelItem serviceLabelItem = (ServiceLabelItem)userObject;
                                int serviceCount = serviceLabelItem.getServiceLinkCount();
                                if (serviceCount > 0)
                                {
                                    removeFlag = JOptionPane.showConfirmDialog(ServiceLabelModulePanel.this, "Метка используется в услугах (" + serviceCount + ").\nПодтвердите удаление.", "Запрос подтверждения", JOptionPane.YES_NO_OPTION) == 0;
                                }
                                if (removeFlag)
                                {
                                    ((DefaultTreeModel)ServiceLabelModulePanel.this.filterLabelTree.getModel()).removeNodeFromParent(serviceLabelTreeNode);
                                    try
                                    {
                                        ServiceLabelModulePanel.this.getContext().getPort(ServiceLabelService.class).removeServiceLabelTreeItem(serviceLabelItem.getId());
                                    }
                                    catch (BGException ex)
                                    {
                                        ServiceLabelModulePanel.this.processException(ex);
                                    }
                                }
                            }
                        }
                    }
                }
            }
        }));
 
        this.popupFilterMenu.add(new JMenuItem(new BGUAction("selectParent", "Выбрать всех родителей")
        {
            public void actionPerformed(ActionEvent event)
            {
                JMenuItem menuItem = (JMenuItem)event.getSource();
                ServiceLabelTree tree = (ServiceLabelTree)((JPopupMenu)menuItem.getParent()).getInvoker();
                Object selectedObject = tree.getLastSelectedPathComponent();
                if ((selectedObject instanceof DefaultMutableTreeNode))
                {
                    DefaultMutableTreeNode serviceLabelTreeNode = (DefaultMutableTreeNode)selectedObject;
                    while (serviceLabelTreeNode != null)
                    {
                        Object userObject = serviceLabelTreeNode.getUserObject();
                        if ((userObject instanceof ServiceLabelItem))
                        {
                            ((ServiceLabelItem)userObject).setSelected(true);
                            ((DefaultTreeModel)tree.getModel()).nodeChanged(serviceLabelTreeNode);
                        }
                        serviceLabelTreeNode = (DefaultMutableTreeNode)serviceLabelTreeNode.getParent();
                    }
                }
                tree.firePropertyChange("changeSelected", false, true);
            }
        }));
        this.popupFilterMenu.add(new JMenuItem(new BGUAction("selectChildren", "Выбрать всех детей")
        {
            public void actionPerformed(ActionEvent event)
            {
                JMenuItem menuItem = (JMenuItem)event.getSource();
                ServiceLabelTree tree = (ServiceLabelTree)((JPopupMenu)menuItem.getParent()).getInvoker();
                Object selectedObject = tree.getLastSelectedPathComponent();
                if ((selectedObject instanceof DefaultMutableTreeNode))
                {
                    DefaultMutableTreeNode serviceLabelTreeNode = (DefaultMutableTreeNode)selectedObject;
                    int selectNodeLevel = serviceLabelTreeNode.getLevel();
                    while (serviceLabelTreeNode != null)
                    {
                        Object userObject = serviceLabelTreeNode.getUserObject();
                        if ((userObject instanceof ServiceLabelItem))
                        {
                            ((ServiceLabelItem)userObject).setSelected(true);
                            ((DefaultTreeModel)tree.getModel()).nodeChanged(serviceLabelTreeNode);
                        }
                        serviceLabelTreeNode = serviceLabelTreeNode.getNextNode();
                        if ((serviceLabelTreeNode != null) && (serviceLabelTreeNode.getLevel() <= selectNodeLevel))
                        {
                            break;
                        }
                    }
                }
                tree.firePropertyChange("changeSelected", false, true);
            }
        }));
        this.popupFilterMenu.add(new JMenuItem(new BGUAction("selectReset", "Сброс выделения")
        {
            public void actionPerformed(ActionEvent event)
            {
                JMenuItem menuItem = (JMenuItem)event.getSource();
                ServiceLabelTree tree = (ServiceLabelTree)((JPopupMenu)menuItem.getParent()).getInvoker();
                DefaultMutableTreeNode node = ((DefaultMutableTreeNode)tree.getModel().getRoot()).getNextNode();
                while (node != null)
                {
                    Object userObject = node.getUserObject();
                    if ((userObject instanceof ServiceLabelItem))
                    {
                        ((ServiceLabelItem)userObject).setSelected(false);
                        ((DefaultTreeModel)tree.getModel()).nodeChanged(node);
                    }
                    node = node.getNextNode();
                }
                tree.firePropertyChange("changeSelected", false, true);
            }
        }));
        ActionListener modeActionListener = new ActionListener()
        {
            public void actionPerformed(ActionEvent event)
            {
                ServiceLabelModulePanel.this.switchLabelMode(event.getActionCommand());
            }
        };
        Dimension dimension = new Dimension(100, 200);
        this.serviceModuleList.setMinimumSize(dimension);
        this.serviceModuleList.setPreferredSize(dimension);
        this.serviceModuleList.addPropertyChangeListener(new PropertyChangeListener()
        {
            public void propertyChange(PropertyChangeEvent event)
            {
                if (("itemChange".equals(event.getPropertyName())) && (ServiceLabelModulePanel.this.serviceModuleList.isEnabled()))
                {
                    ServiceLabelModulePanel.this.setData();
                }
            }
        });
        this.labelModePanel = new JPanel(new GridBagLayout())
        {
            public void setEnabled(boolean enabled)
            {
                super.setEnabled(enabled);
                for (int index = 0; index < getComponentCount(); index++)
                {
                    getComponent(index).setEnabled(enabled);
                }
            }
        };
        ButtonGroup modeButtonGroup = new ButtonGroup();
        this.labelModePanel.add(new JLabel("Метки:"), new GridBagConstraints(0, 0, 1, 1, 1.0D, 0.0D, 18, 0, new Insets(0, 0, 0, 5), 0, 0));
        this.labelModePanel.add(new ModeButton("filter", modeButtonGroup, modeActionListener, "Фильтр"), new GridBagConstraints(1, 0, 1, 1, 0.0D, 0.0D, 10, 0, new Insets(0, 0, 0, 0), 0, 0));
        this.labelModePanel.add(new ModeButton("editor", modeButtonGroup, modeActionListener, "Редактор"), new GridBagConstraints(2, 0, 1, 1, 0.0D, 0.0D, 10, 0, new Insets(0, 0, 0, 0), 0, 0));
 
        modeButtonGroup.setSelected(modeButtonGroup.getElements().nextElement().getModel(), true);
 
        int y = 0;
        JPanel panel = new JPanel(new GridBagLayout());
        panel.setBorder(new BGTitleBorder(" Фильтр "));
        panel.add(new JLabel("Модули:"), new GridBagConstraints(0, y++, 2, 1, 0.0D, 0.0D, 17, 0, new Insets(0, 5, 0, 5), 0, 0));
        panel.add(this.serviceModuleList, new GridBagConstraints(0, y++, 2, 1, 1.0D, 0.0D, 10, 2, new Insets(0, 0, 5, 0), 0, 0));
        panel.add(this.labelModePanel, new GridBagConstraints(0, y++, 2, 1, 0.0D, 0.0D, 17, 2, new Insets(0, 5, 5, 5), 0, 0));
        //noinspection UnusedAssignment
        panel.add(new JScrollPane(this.filterLabelTree), new GridBagConstraints(0, y++, 2, 1, 1.0D, 1.0D, 10, 1, new Insets(0, 5, 5, 5), 0, 0));
        return panel;
    }
 
    private void switchLabelMode(String mode)
    {
        if ("editor".equals(mode))
        {
            this.serviceTable.setEnabled(false);
            this.serviceModuleList.setEnabled(false);
 
            this.filterLabelTree.setEditable(true);
            this.filterLabelTree.offNodeSelectionListener();
            this.filterLabelTree.setComponentPopupMenu(this.popupEditorMenu);
            this.filterLabelTree.setCellRenderer(new ModeEditorTreeCellRenderer());
        }
        else
        {
            this.serviceTable.setEnabled(true);
            this.serviceModuleList.setEnabled(true);
 
            this.filterLabelTree.setEditable(false);
            this.filterLabelTree.onNodeSelectionListener();
            this.filterLabelTree.setComponentPopupMenu(this.popupFilterMenu);
            this.filterLabelTree.setCellRenderer(new ServiceLabelTreeCellRenderer());
        }
    }
 
    class ModeEditorTreeCellRenderer extends DefaultTreeCellRenderer
    {
        public ModeEditorTreeCellRenderer()
        {
            setOpenIcon(ClientUtils.getIcon("node.png"));
            setClosedIcon(ClientUtils.getIcon("node.png"));
            setLeafIcon(ClientUtils.getIcon("leaf.png"));
        }
    }
 
    class TransferableServiceLabelItem
            implements Transferable
    {
        DataFlavor SERVICE_LABEL_ITEM_FLAVOR = new DataFlavor(ServiceLabelItem.class, "ServiceLabelItem");
        DataFlavor[] flavors = { this.SERVICE_LABEL_ITEM_FLAVOR };
        Object object;
 
        public TransferableServiceLabelItem(Object object)
        {
            this.object = object;
        }
 
        public synchronized DataFlavor[] getTransferDataFlavors()
        {
            return this.flavors;
        }
 
        public boolean isDataFlavorSupported(DataFlavor flavor)
        {
            return flavor.getRepresentationClass() == ServiceLabelItem.class;
        }
 
        public synchronized Object getTransferData(DataFlavor flavor)
                throws UnsupportedFlavorException, IOException
        {
            if (isDataFlavorSupported(flavor))
            {
                return this.object;
            }
 
            throw new UnsupportedFlavorException(flavor);
        }
    }
 
    class TreeDragSource implements DragSourceListener, DragGestureListener {
        DragSource source;
        DragGestureRecognizer recognizer;
        ServiceLabelModulePanel.TransferableServiceLabelItem transferable;
        DefaultMutableTreeNode oldNode;
        JTree sourceTree;
 
        public TreeDragSource(JTree tree, int actions) {
            this.sourceTree = tree;
            this.source = new DragSource();
            this.recognizer = this.source.createDefaultDragGestureRecognizer(this.sourceTree, actions, this);
        }
 
        public void dragGestureRecognized(DragGestureEvent event)
        {
            TreePath path = this.sourceTree.getSelectionPath();
            if ((path != null) && (path.getPathCount() > 1))
            {
                this.oldNode = ((DefaultMutableTreeNode)path.getLastPathComponent());
                if ((this.oldNode.isLeaf()) && (this.sourceTree.isEditable()))
                {
                    this.transferable = new ServiceLabelModulePanel.TransferableServiceLabelItem(this.oldNode.getUserObject());
                    event.startDrag(DragSource.DefaultMoveDrop, this.transferable, this);
                }
            }
        }
 
        public void dragEnter(DragSourceDragEvent dragSourceDragEvent)
        {
        }
 
        public void dragExit(DragSourceEvent dragSourceEvent)
        {
        }
 
        public void dragOver(DragSourceDragEvent dragSourceDragEvent)
        {
        }
 
        public void dropActionChanged(DragSourceDragEvent dragSourceDragEvent)
        {
        }
 
        public void dragDropEnd(DragSourceDropEvent event)
        {
            if ((event.getDropSuccess()) && (event.getDropAction() == 2))
            {
                ((DefaultTreeModel)this.sourceTree.getModel()).removeNodeFromParent(this.oldNode);
            }
        }
    }
 
    class TreeDropTarget
            implements DropTargetListener
    {
        DropTarget target;
        JTree targetTree;
 
        public TreeDropTarget(JTree tree)
        {
            this.targetTree = tree;
            this.target = new DropTarget(this.targetTree, this);
        }
 
        public void dragEnter(DropTargetDragEvent event)
        {
            event.acceptDrag(event.getDropAction());
        }
 
        public void dragOver(DropTargetDragEvent event)
        {
        }
 
        public void dragExit(DropTargetEvent event)
        {
        }
 
        public void dropActionChanged(DropTargetDragEvent event)
        {
        }
 
        public void drop(DropTargetDropEvent event)
        {
            Point point = event.getLocation();
            JTree tree = (JTree)event.getDropTargetContext().getComponent();
            TreePath parentPath = tree.getClosestPathForLocation(point.x, point.y);
            if (parentPath != null)
            {
                try
                {
                    Transferable transferable = event.getTransferable();
                    DataFlavor[] flavors = transferable.getTransferDataFlavors();
                    for (DataFlavor flavor : flavors) {
                        if (transferable.isDataFlavorSupported(flavor)) {
                            DefaultMutableTreeNode parent = (DefaultMutableTreeNode) parentPath.getLastPathComponent();
                            ServiceLabelItem parentServiceLabelItem = (ServiceLabelItem) parent.getUserObject();
 
                            ServiceLabelItem serviceLabelItem = (ServiceLabelItem) transferable.getTransferData(flavor);
                            if (parentServiceLabelItem.getId() == serviceLabelItem.getId()) {
                                break;
                            }
 
                            serviceLabelItem.setParentId(parentServiceLabelItem.getId());
 
                            event.acceptDrop(event.getDropAction());
 
                            DefaultMutableTreeNode newServiceLabelTreeNode = new DefaultMutableTreeNode();
                            newServiceLabelTreeNode.setUserObject(serviceLabelItem);
 
                            DefaultTreeModel defaultTreeModel = (DefaultTreeModel) tree.getModel();
                            defaultTreeModel.insertNodeInto(newServiceLabelTreeNode, parent, parent.getChildCount());
                            try
                            {
                                ServiceLabelModulePanel.this.getContext().getPort(ServiceLabelService.class).updateServiceLabelTreeItem(serviceLabelItem);
                            }
                            catch (BGException ex)
                            {
                                ServiceLabelModulePanel.this.processException(ex);
                            }
                            tree.expandPath(new TreePath(parent.getPath()));
                            tree.scrollPathToVisible(new TreePath(parent.getPath()));
                            event.dropComplete(true);
                            return;
                        }
                    }
                    event.rejectDrop();
                }
                catch (Exception e)
                {
                    e.printStackTrace();
                    event.rejectDrop();
                }
            }
            else
            {
                event.rejectDrop();
            }
        }
    }
 
    private class ServiceTreeCellEditor implements TreeCellEditor
    {
        private Object editValue;
 
        public boolean stopCellEditing()
        {
            return true;
        }
 
        public boolean shouldSelectCell(EventObject anEvent)
        {
            return false;
        }
 
        public void removeCellEditorListener(CellEditorListener l)
        {
        }
 
        public boolean isCellEditable(EventObject anEvent)
        {
            boolean result = anEvent == null;
            if (!result)
            {
                ServiceLabelTree tree = (ServiceLabelTree)anEvent.getSource();
                if ((anEvent instanceof MouseEvent))
                {
                    MouseEvent mouseEvent = (MouseEvent)anEvent;
                    TreePath treePath = tree.getPathForLocation(mouseEvent.getX(), mouseEvent.getY());
                    if(treePath!=null){
                        Object selectedObject = treePath.getLastPathComponent();
                        if ((selectedObject instanceof DefaultMutableTreeNode))
                        {
                            DefaultMutableTreeNode serviceLabelTreeNode = (DefaultMutableTreeNode)selectedObject;
                            if (serviceLabelTreeNode.isRoot())
                            {
                                result = false;
                            }
                        }
                    }
                }
            }
            return result;
        }
 
        public Object getCellEditorValue()
        {
            return this.editValue;
        }
 
        public void cancelCellEditing()
        {
        }
 
        public void addCellEditorListener(CellEditorListener l)
        {
        }
 
        public Component getTreeCellEditorComponent(final JTree tree, Object value, boolean isSelected, boolean expanded, boolean leaf, int row) {
            final JTextField comp = new JTextField();
 
            comp.addKeyListener(new KeyAdapter()
            {
                public void keyReleased(KeyEvent keyEvent)
                {
                    if (keyEvent.getKeyCode() == 10)
                    {
                        ServiceLabelItem tariffLabelItem = (ServiceLabelItem)ServiceTreeCellEditor.this.editValue;
                        tariffLabelItem.setTitle(comp.getText());
                        try
                        {
                            (ServiceLabelModulePanel.this.getContext().getPort(ServiceLabelService.class)).updateServiceLabelTreeItem(tariffLabelItem);
                        }
                        catch (BGException ex)
                        {
                            ServiceLabelModulePanel.this.processException(ex);
                        }
                        tree.stopEditing();
                        ServiceLabelModulePanel.this.setLabelTreeData(ServiceLabelModulePanel.this.filterLabelTree, -1);
                    }
                }
            });
            if ((value instanceof DefaultMutableTreeNode))
            {
                this.editValue = ((DefaultMutableTreeNode)value).getUserObject();
                comp.setText(this.editValue.toString());
                comp.setBorder(BorderFactory.createLineBorder(Color.gray, 1));
            }
 
            comp.repaint();
 
            return row > 0 ? comp : null;
        }
    }
 
    class ModeButton extends JToggleButton
    {
        ModeButton(String actionCommand, ButtonGroup buttonGroup, ActionListener actionListener, String toolTipText)
        {
            setMargin(new Insets(0, 0, 0, 0));
            setPreferredSize(new Dimension(20, 16));
            setToolTipText(toolTipText);
            buttonGroup.add(this);
            addActionListener(actionListener);
            setActionCommand(actionCommand);
            setText(String.valueOf(toolTipText.charAt(0)));
        }
    }
}

Контрол дерева меток:

package ru.dsi.bgbilling.kernel.module.client;
 
import ru.dsi.bgbilling.kernel.module.common.bean.ServiceLabelItem;
import ru.dsi.bgbilling.kernel.module.common.bean.ServiceLabelTreeCellRenderer;
 
import javax.swing.*;
import javax.swing.tree.DefaultMutableTreeNode;
import javax.swing.tree.DefaultTreeModel;
import javax.swing.tree.TreePath;
import javax.swing.tree.TreeSelectionModel;
import java.awt.*;
import java.awt.dnd.Autoscroll;
import java.awt.event.*;
import java.util.ArrayList;
import java.util.List;
 
public class ServiceLabelTree extends JTree
        implements Autoscroll
{
    private int margin = 12;
    private NodeSelectionListener listener = new NodeSelectionListener();
 
    public ServiceLabelTree()
    {
        setBorder(BorderFactory.createEmptyBorder(3, 3, 3, 3));
        setCellRenderer(new ServiceLabelTreeCellRenderer());
        setRootVisible(true);
        setShowsRootHandles(true);
        getSelectionModel().setSelectionMode(TreeSelectionModel.SINGLE_TREE_SELECTION);
        onNodeSelectionListener();
    }
 
    public void setData(List<ServiceLabelItem> serviceLabelItemList)
    {
        ServiceLabelItem root = new ServiceLabelItem();
        root.setTitle("Корневой эелемент");
        setModel(new DefaultTreeModel(new DefaultMutableTreeNode(root)));
        buildServiceLabelTree((DefaultMutableTreeNode) getModel().getRoot(), serviceLabelItemList, 0);
 
        DefaultMutableTreeNode node = ((DefaultMutableTreeNode)getModel().getRoot()).getNextNode();
        while (node != null)
        {
            expandPath(new TreePath(node.getPath()));
            node = node.getNextNode();
        }
    }
 
    public List<ServiceLabelItem> getSelectedItems()
    {
        List<ServiceLabelItem> serviceLabelItemList = new ArrayList<ServiceLabelItem>();
        DefaultMutableTreeNode node = ((DefaultMutableTreeNode)getModel().getRoot()).getNextNode();
        while (node != null)
        {
            Object userObject = node.getUserObject();
            if (((userObject instanceof ServiceLabelItem)) && (((ServiceLabelItem)userObject).isSelected()))
            {
                serviceLabelItemList.add((ServiceLabelItem)userObject);
            }
            node = node.getNextNode();
        }
        return serviceLabelItemList;
    }
 
    public List<Integer> getSelectedIds()
    {
        List<Integer> ids = new ArrayList<Integer>();
        DefaultMutableTreeNode node = ((DefaultMutableTreeNode)getModel().getRoot()).getNextNode();
        while (node != null)
        {
            Object userObject = node.getUserObject();
            if (((userObject instanceof ServiceLabelItem)) && (((ServiceLabelItem)userObject).isSelected()))
            {
                ids.add(((ServiceLabelItem)userObject).getId());
            }
            node = node.getNextNode();
        }
        return ids;
    }
 
    private void buildServiceLabelTree(DefaultMutableTreeNode currentNode, List<ServiceLabelItem> serviceLabelItemList, int parentId)
    {
        for (ServiceLabelItem serviceLabelItem : serviceLabelItemList)
        {
            if (serviceLabelItem.getParentId() == parentId)
            {
                DefaultMutableTreeNode labelTreeNode = new DefaultMutableTreeNode();
                labelTreeNode.setUserObject(serviceLabelItem);
                currentNode.add(labelTreeNode);
                buildServiceLabelTree(labelTreeNode, serviceLabelItemList, serviceLabelItem.getId());
            }
        }
    }
 
    public String convertValueToText(Object value, boolean selected, boolean expanded, boolean leaf, int row, boolean hasFocus)
    {
        String text = super.convertValueToText(value, selected, expanded, leaf, row, hasFocus);
        if (((value instanceof DefaultMutableTreeNode)) && (!isEditable()))
        {
            DefaultMutableTreeNode servicefLabelTreeNode = (DefaultMutableTreeNode)value;
            Object userObject = servicefLabelTreeNode.getUserObject();
            if ((userObject instanceof ServiceLabelItem))
            {
                ServiceLabelItem serviceLabelItem = (ServiceLabelItem)userObject;
                if (serviceLabelItem.getServiceLinkCount() > 0)
                {
                    text = text.concat(" [").concat(String.valueOf(serviceLabelItem.getServiceLinkCount())).concat("]");
                }
            }
        }
        return text;
    }
 
    public void onNodeSelectionListener()
    {
        boolean fl = true;
        for (MouseListener mouseListener : getMouseListeners())
        {
            if (mouseListener == this.listener)
            {
                fl = false;
                break;
            }
        }
        if (fl) addMouseListener(this.listener);
 
        fl = true;
        for (KeyListener keyListener : getKeyListeners())
        {
            if (keyListener == this.listener)
            {
                fl = false;
                break;
            }
        }
        if (fl) addKeyListener(this.listener);
    }
 
    public void offNodeSelectionListener()
    {
        removeMouseListener(this.listener);
        removeKeyListener(this.listener);
    }
 
    public Insets getAutoscrollInsets()
    {
        Rectangle outer = getBounds();
        Rectangle inner = getParent().getBounds();
        return new Insets(inner.y - outer.y + this.margin, inner.x - outer.x + this.margin, outer.height - inner.height - inner.y + outer.y + this.margin, outer.width - inner.width - inner.x + outer.x + this.margin);
    }
 
    public void autoscroll(Point p)
    {
        int realrow = getRowForLocation(p.x, p.y);
        Rectangle outer = getBounds();
        realrow = realrow < getRowCount() - 1 ? realrow + 1 : p.y + outer.y <= this.margin ? realrow - 1 : realrow < 1 ? 0 : realrow;
        scrollRowToVisible(realrow);
    }
 
    private final class NodeSelectionListener extends MouseAdapter
            implements KeyListener
    {
        private NodeSelectionListener()
        {
        }
 
        public void mouseReleased(MouseEvent e)
        {
            int x = e.getX();
            int y = e.getY();
            int row = ServiceLabelTree.this.getRowForLocation(x, y);
            TreePath path = ServiceLabelTree.this.getPathForRow(row);
            if (path != null)
            {
                if (SwingUtilities.isLeftMouseButton(e))
                {
                    Object selectedObject = ServiceLabelTree.this.getLastSelectedPathComponent();
                    if ((selectedObject instanceof DefaultMutableTreeNode)) action((DefaultMutableTreeNode)selectedObject);
                }
            }
        }
 
        public final void keyReleased(KeyEvent keyevent)
        {
            int i;
            if (((i = keyevent.getKeyCode()) == 32) || (i == 10))
            {
                action((DefaultMutableTreeNode)ServiceLabelTree.this.getLastSelectedPathComponent());
            }
        }
 
        public void keyPressed(KeyEvent e)
        {
        }
 
        public void keyTyped(KeyEvent e)
        {
        }
 
        private void action(DefaultMutableTreeNode node)
        {
            if (node == null)
            {
                return;
            }
 
            Object userObject = node.getUserObject();
            if ((userObject instanceof ServiceLabelItem))
            {
                ServiceLabelItem serviceLabelItem = (ServiceLabelItem)userObject;
                serviceLabelItem.setSelected(!serviceLabelItem.isSelected());
                ServiceLabelTree.this.firePropertyChange("changeSelected", !serviceLabelItem.isSelected(), serviceLabelItem.isSelected());
                ServiceLabelTree.this.repaint();
            }
        }
    }
}
Личные инструменты