package com.fr.design.gui.controlpane; import com.fr.design.beans.BasicBeanPane; import com.fr.design.constants.UIConstants; import com.fr.design.gui.icontainer.UIScrollPane; import com.fr.design.gui.ilist.JNameEdList; import com.fr.design.gui.ilist.ListModelElement; import com.fr.design.gui.ilist.UINameEdList; import com.fr.design.mainframe.DesignerContext; import com.fr.design.os.impl.PopupDialogSaveAction; import com.fr.design.utils.gui.GUICoreUtils; import com.fr.stable.ArrayUtils; import com.fr.stable.Nameable; import com.fr.stable.os.support.OSSupportCenter; import javax.swing.DefaultListModel; import javax.swing.JList; import javax.swing.JPanel; import javax.swing.JPopupMenu; import javax.swing.ListSelectionModel; import javax.swing.SwingUtilities; import javax.swing.event.ListDataEvent; import javax.swing.event.ListDataListener; import javax.swing.event.ListSelectionEvent; import javax.swing.event.ListSelectionListener; import java.awt.BorderLayout; import java.awt.Point; import java.awt.Rectangle; import java.awt.Toolkit; import java.awt.Window; import java.awt.event.InputEvent; import java.awt.event.MouseAdapter; import java.awt.event.MouseEvent; import java.awt.event.MouseListener; import java.lang.reflect.Constructor; import java.lang.reflect.InvocationTargetException; /** * Created by plough on 2017/7/19. */ public abstract class UIListControlPane extends UIControlPane implements ListControlPaneProvider { private static final String LIST_NAME = "UIControl_List"; private static final int EDIT_RANGE = 25; // 编辑按钮的x坐标范围 protected UINameEdList nameableList; private int editingIndex; protected String selectedName; protected boolean isPopulating = false; private CommonShortCutHandlers commonHandlers; private ListControlPaneHelper helper; public UIListControlPane() { super(); } private ListControlPaneHelper getHelper() { if (helper == null) { helper = ListControlPaneHelper.newInstance(this); } return helper; } private CommonShortCutHandlers getCommonHandlers() { if (commonHandlers == null) { commonHandlers = CommonShortCutHandlers.newInstance(this); } return commonHandlers; } @Override protected JPanel createControlUpdatePane() { return JControlUpdatePane.newInstance(this); } /** * 生成添加按钮的NameableCreator * * @return 按钮的NameableCreator */ @Override public abstract NameableCreator[] createNameableCreators(); @Override protected void initLeftPane(JPanel leftPane) { nameableList = createJNameList(); nameableList.setName(LIST_NAME); nameableList.setSelectionBackground(UIConstants.ATTRIBUTE_PRESS); leftPane.add(new UIScrollPane(nameableList), BorderLayout.CENTER); nameableList.setSelectionMode(ListSelectionModel.MULTIPLE_INTERVAL_SELECTION); nameableList.addMouseListener(getListMouseListener()); nameableList.addListSelectionListener(new ListSelectionListener() { public void valueChanged(ListSelectionEvent evt) { // richie:避免多次update和populate大大降低效率 if (!evt.getValueIsAdjusting()) { // shoc 切换的时候加检验 if (hasInvalid(false)) { return; } ((JControlUpdatePane) UIListControlPane.this.controlUpdatePane).update(); ((JControlUpdatePane) UIListControlPane.this.controlUpdatePane).populate(); UIListControlPane.this.checkButtonEnabled(); } } }); if (isNewStyle()) { nameableList.getModel().addListDataListener(new ListDataListener() { @Override public void intervalAdded(ListDataEvent e) { saveSettings(); } @Override public void intervalRemoved(ListDataEvent e) { saveSettings(); } @Override public void contentsChanged(ListDataEvent e) { saveSettings(); } }); } } private UINameEdList createJNameList() { UINameEdList nameEdList = new UINameEdList(new DefaultListModel()) { @Override protected void doAfterLostFocus() { UIListControlPane.this.updateControlUpdatePane(); } @Override protected void doAfterStopEditing() { saveSettings(); } }; nameEdList.setCellRenderer(new UINameableListCellRenderer(this)); return nameEdList; } private void updateControlUpdatePane() { ((JControlUpdatePane) controlUpdatePane).update(); } protected void setNameListEditable(boolean editable) { this.nameableList.setEditable(editable); } @Override public Nameable[] update() { return getHelper().update(); } @Override public void populate(Nameable[] nameableArray) { isPopulating = true; // 加一个标识位,避免切换单元格时,触发 saveSettings nameableList.getCellEditor().stopCellEditing(); DefaultListModel listModel = (DefaultListModel) this.nameableList.getModel(); listModel.removeAllElements(); if (ArrayUtils.isEmpty(nameableArray)) { isPopulating = false; return; } listModel.setSize(nameableArray.length); for (int i = 0; i < nameableArray.length; i++) { listModel.set(i, new ListModelElement(nameableArray[i])); } if (listModel.size() > 0 || this.nameableList.getSelectedIndex() != 0) { this.nameableList.setSelectedIndex(0); } this.checkButtonEnabled(); isPopulating = false; } /** * 获取选中的名字 */ public String getSelectedName() { return getHelper().getSelectedName(); } /** * 添加 Nameable * * @param nameable 添加的Nameable * @param index 序号 */ public void addNameable(Nameable nameable, int index) { getHelper().addNameable(nameable, index); popupEditDialog(); } public DefaultListModel getModel() { return (DefaultListModel) UIListControlPane.this.nameableList.getModel(); } private void popupEditDialog() { popupEditDialog(null); } protected void popupEditDialog(Point mousePos) { if (isNewStyle()) { Rectangle currentCellBounds = nameableList.getCellBounds(editingIndex, editingIndex); if (editingIndex < 0 || (mousePos != null && !currentCellBounds.contains(mousePos))) { return; } popupEditDialog.setLocation(getPopupDialogLocation()); if (popupEditDialog instanceof PopupEditDialog) { ((PopupEditDialog)popupEditDialog).setTitle(getSelectedName()); } popupEditDialog.setVisible(true); PopupDialogSaveAction osBasedAction = OSSupportCenter.getAction(PopupDialogSaveAction.class); osBasedAction.register(this, popupEditDialog); } } private Point getPopupDialogLocation() { Point resultPos = new Point(0, 0); Point listPos = nameableList.getLocationOnScreen(); resultPos.x = listPos.x - popupEditDialog.getWidth(); resultPos.y = listPos.y + (nameableList.getSelectedIndex() - 1) * EDIT_RANGE; // 当对象在屏幕上的位置比较靠下时,往下移动弹窗至与属性面板平齐 Window frame = DesignerContext.getDesignerFrame(); // 不能太低 int maxY = frame.getLocationOnScreen().y + frame.getHeight() - popupEditDialog.getHeight(); if (resultPos.y > maxY) { resultPos.y = maxY; } // 也不能太高 int minY = frame.getLocationOnScreen().y + EDIT_RANGE; if (resultPos.y < minY) { resultPos.y = minY; } // 当在左侧显示不下时,在右侧弹出弹窗 if (resultPos.x < 0) { resultPos.x = listPos.x + nameableList.getParent().getWidth(); } // 如果右侧显示不下,可以向左移动 int maxX = frame.getLocationOnScreen().x + frame.getWidth() - popupEditDialog.getWidth() - EDIT_RANGE; if (resultPos.x > maxX) { resultPos.x = maxX; } return resultPos; } /** * 生成不重复的名字 * * @param prefix 名字前缀 * @return 名字 */ @Override public String createUnrepeatedName(String prefix) { return getCommonHandlers().createUnrepeatedName(prefix); } @Override public void onAddItem(NameableCreator creator) { getCommonHandlers().onAddItem(creator); } @Override public void onRemoveItem() { getCommonHandlers().onRemoveItem(); } @Override public void onCopyItem() { getCommonHandlers().onCopyItem(); } @Override public void onMoveUpItem() { getCommonHandlers().onMoveUpItem(); } @Override public void onMoveDownItem() { getCommonHandlers().onMoveDownItem(); } @Override public void onSortItem(boolean isAtoZ) { getCommonHandlers().onSortItem(isAtoZ); } @Override public boolean isItemSelected() { return getModel().getSize() > 0 && nameableList.getSelectedIndex() != -1; } /* * UINameEdList的鼠标事件 */ private MouseListener getListMouseListener() { return new MouseAdapter() { @Override public void mouseReleased(MouseEvent evt) { nameableList.stopEditing(); if (evt.getClickCount() >= 2 && SwingUtilities.isLeftMouseButton(evt) && evt.getX() > EDIT_RANGE) { editingIndex = nameableList.getSelectedIndex(); selectedName = nameableList.getNameAt(editingIndex); nameableList.editItemAt(nameableList.getSelectedIndex()); } else if (SwingUtilities.isLeftMouseButton(evt) && evt.getX() <= EDIT_RANGE) { editingIndex = nameableList.getSelectedIndex(); selectedName = nameableList.getNameAt(editingIndex); popupEditDialog(evt.getPoint()); } // peter:处理右键的弹出菜单 if (!SwingUtilities.isRightMouseButton(evt)) { return; } // peter: 注意,在checkButtonEnabled()方法里面,设置了所有的Action的Enabled. checkButtonEnabled(); // p:右键菜单. JPopupMenu popupMenu = new JPopupMenu(); for (ShortCut4JControlPane sj : getShorts()) { sj.getShortCut().intoJPopupMenu(popupMenu); } // peter: 只有弹出菜单有子菜单的时候,才需要弹出来. GUICoreUtils.showPopupMenu(popupMenu, nameableList, evt.getX() - 1, evt.getY() - 1); } @Override public void mouseClicked(MouseEvent e) { JList list = (JList) e.getSource(); if (list.locationToIndex(e.getPoint()) == -1 && !e.isShiftDown() && !isMenuShortcutKeyDown(e)) { list.clearSelection(); } } private boolean isMenuShortcutKeyDown(InputEvent event) { return (event.getModifiers() & Toolkit.getDefaultToolkit() .getMenuShortcutKeyMask()) != 0; } @Override public void mouseMoved(MouseEvent e) { } }; } /** * 检查按钮可用状态 Check button enabled. */ @Override public void checkButtonEnabled() { getHelper().checkButtonEnabled(); } public BasicBeanPane createPaneByCreators(NameableCreator creator) { try { return creator.getUpdatePane().newInstance(); } catch (InstantiationException e) { throw new RuntimeException(e); } catch (IllegalAccessException e) { throw new RuntimeException(e); } } public BasicBeanPane createPaneByCreators(NameableCreator creator, String string) { Constructor constructor = null; try { constructor = creator.getUpdatePane().getDeclaredConstructor(new Class[]{String.class}); constructor.setAccessible(true); return (BasicBeanPane) constructor.newInstance(string); } catch (NoSuchMethodException e) { throw new RuntimeException(e); } catch (InstantiationException e) { throw new RuntimeException(e); } catch (IllegalAccessException e) { throw new RuntimeException(e); } catch (InvocationTargetException e) { throw new RuntimeException(e); } } /** * 检查是否符合规范 * * @throws Exception */ @Override public void checkValid() throws Exception { ((JControlUpdatePane) this.controlUpdatePane).checkValid(); } @Override public boolean hasInvalid(boolean isAdd) { return getHelper().hasInvalid(isAdd); } /** * 设置选中项 * * @param index 选中项的序列号 */ public void setSelectedIndex(int index) { nameableList.setSelectedIndex(index); } @Override public int getSelectedIndex() { return nameableList.getSelectedIndex(); } @Override public ListModelElement getSelectedValue() { return (ListModelElement) this.nameableList.getSelectedValue(); } @Override public JControlUpdatePane getControlUpdatePane() { return (JControlUpdatePane) controlUpdatePane; } @Override public JNameEdList getNameableList() { return nameableList; } }