Метки услуг
Материал из BiTel WiKi
(Удалено содержимое страницы) |
м (переименовал «Service labels» в «Метки услуг») |
||
(5 промежуточных версий не показаны.) | |||
Строка 1: | Строка 1: | ||
+ | = Описание = | ||
+ | Для отчётов полезно иметь группировку услуг по типам вне зависимости от модуля. | ||
+ | Например, группа услуг "Интернет" - туда могут входить как услуги трафиков модулей Inet, Dialup, IPN, так и абонплаты за интернет. | ||
+ | Аналогично, "VPN" | ||
+ | Было решено сделать группировку аналогично меткам тарифов - в виде дерева меток. | ||
+ | |||
+ | Решение состоит из серверного API и клиентского интерфейса. | ||
+ | Решение является упрощённой копипастой стандартной работы с метками тарифов. | ||
+ | |||
+ | [[Файл:service_labels_1.png]] | ||
+ | |||
+ | = Общие классы = | ||
+ | Классы, которые должны быть как в серверных библиотеках, так и в клиентских | ||
+ | |||
+ | Во-первых, нам понадобится веб-сервис для работы с метками тарифов: | ||
+ | |||
+ | <source lang="java"> | ||
+ | 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; | ||
+ | } | ||
+ | </source> | ||
+ | |||
+ | Элемент списка услуг для отображения: | ||
+ | |||
+ | <source lang="java"> | ||
+ | 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; | ||
+ | } | ||
+ | } | ||
+ | </source> | ||
+ | |||
+ | Элемент дерева меток: | ||
+ | <source lang="java"> | ||
+ | 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; | ||
+ | } | ||
+ | } | ||
+ | </source> | ||
+ | |||
+ | Renderer дерева меток: | ||
+ | |||
+ | <source lang="java"> | ||
+ | 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); | ||
+ | } | ||
+ | } | ||
+ | </source> | ||
+ | |||
+ | |||
+ | |||
+ | = Сервер = | ||
+ | == Таблицы mysql == | ||
+ | Таблицы аналогичны таблицам меток тарифов tariff_label и tariff_label_link | ||
+ | |||
+ | <source lang="sql"> | ||
+ | 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`) | ||
+ | ) | ||
+ | </source> | ||
+ | |||
+ | == Классы java == | ||
+ | |||
+ | Реализация веб-сервиса меток услуг | ||
+ | <source lang="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; | ||
+ | } | ||
+ | |||
+ | } | ||
+ | </source> | ||
+ | |||
+ | Dao для работы с метками (группами) услуг: | ||
+ | <source lang="java"> | ||
+ | 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; | ||
+ | } | ||
+ | } | ||
+ | </source> | ||
+ | |||
+ | = Клиентские классы = | ||
+ | |||
+ | В файл '''/bitel/billing/module/services/npay/setup_user.properties''' пропишем нашу панель как вкладку модуля абонплат с названием «Группы услуг» | ||
+ | <source lang=ini> | ||
+ | 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 | ||
+ | </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> |
Текущая версия на 08:23, 21 апреля 2013
Содержание |
Описание
Для отчётов полезно иметь группировку услуг по типам вне зависимости от модуля. Например, группа услуг "Интернет" - туда могут входить как услуги трафиков модулей Inet, Dialup, IPN, так и абонплаты за интернет. Аналогично, "VPN"
Было решено сделать группировку аналогично меткам тарифов - в виде дерева меток.
Решение состоит из серверного API и клиентского интерфейса. Решение является упрощённой копипастой стандартной работы с метками тарифов.
Общие классы
Классы, которые должны быть как в серверных библиотеках, так и в клиентских
Во-первых, нам понадобится веб-сервис для работы с метками тарифов:
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(); } } } }