?? selectionmodel.java
字號:
/*
* SelectionModel.java
*
* Created on 2007年5月7日, 下午9:58
*
* To change this template, choose Tools | Template Manager
* and open the template in the editor.
*/
package dyno.swing.designer.beans.models;
import dyno.swing.beans.layouts.AbsoluteLayout;
import dyno.swing.designer.beans.AdapterBus;
import dyno.swing.designer.beans.ComponentAdapter;
import dyno.swing.designer.beans.Constants;
import dyno.swing.designer.beans.ContainerAdapter;
import dyno.swing.designer.beans.SwingDesigner;
import dyno.swing.designer.beans.Util;
import dyno.swing.designer.beans.events.DesignerEvent;
import java.awt.Component;
import java.awt.Container;
import java.awt.LayoutManager;
import java.awt.Rectangle;
import java.awt.Toolkit;
import java.awt.event.MouseEvent;
import java.util.ArrayList;
import java.util.Collection;
import javax.swing.JViewport;
import javax.swing.SwingUtilities;
/**
* 該model保存當前選擇的組件和剪切版信息
* @author William Chen
*/
public class SelectionModel implements Constants {
private SwingDesigner designer;
//當前選中的組件,可以是多選,被選中的組件之間可以存在父子樹狀關系
private transient ArrayList<Component> selection;
//當前被拷貝或粘帖的剪切板
private transient ArrayList<Component> clip_board;
//當前拖拽和選擇的熱點區域
private transient Rectangle hotspot_bounds;
public SelectionModel(SwingDesigner designer) {
this.designer = designer;
selection = new ArrayList<Component>();
clip_board = new ArrayList<Component>();
}
public void reset(){
selection.clear();
clip_board.clear();
hotspot_bounds=null;
}
/**
* 當前選擇的組件是否是可以拖拽的??梢酝献У臈l件為:
* 1.選中的組件不為空(很明顯)
* 2.選中的組件不是根組件
* 3.選中的組件的父親容器必須是同一個容器(不同容器內的組件不可以被同時拖拽)
* 4.選中的組件的父親容器的布局管理器為空,或者是AbsoluteLayout。這個規則以后可能發生,
* 如果想在其他布局管理器的情況下支持特殊的拖拽。待定。
*
* @return 是否可以拖拽,是為true,否則false
*/
public boolean isSelectedResizable() {
if (selection.isEmpty()) {
//1.選中的組件不為空
return false;
}
Container current = null;
for (Component comp : selection) {
Container parent = comp.getParent();
if ((parent == null) || (comp == designer.getRootComponent())) {
//2.選中的組件不是根組件
return false;
}
LayoutManager layout = parent.getLayout();
if ((layout != null) && (layout.getClass() != AbsoluteLayout.class)) {
//4.選中的組件的父親容器的布局管理器為空,或者是AbsoluteLayout
return false;
}
if (current == null) {
//第一個組件的父容器
current = parent;
} else if (current != parent) {
//3.選中的組件的父親容器必須是同一個容器
return false;
}
}
return true;
}
public void setSelectedComponent(Component comp) {
selection.clear();
selection.add(comp);
fireComponentSelected();
}
/**
* 鼠標點擊一下,所選中的單個組件。按下Ctrl或者shift鍵時鼠標可以進行多選
*/
public void selectAComponentAtMouseEvent(MouseEvent e) {
if (!e.isControlDown() && !e.isShiftDown()) {
//如果Ctrl或者Shift鍵盤沒有按下,則清除已經選擇的組件
selection.clear();
}
//獲取e所在的組件
Component comp = designer.getComponentAt(e);
if (!((comp == null) || selection.contains(comp))) {
//如果e所在的地方有組件,并且已經選中的組件中不包含此組件,則添加進去
selection.add(comp);
}
//觸發鼠標組件選擇事件。
fireComponentSelected();
designer.repaint();
}
private void fireComponentSelected() {
DesignerEvent evt = new DesignerEvent(this);
evt.setSelectedComponents(selection);
designer.getEditListenerTable().fireComponentSelected(evt);
}
/**
* 在當前選中的組件中找出處于e鼠標事件所在的組件。
*/
public Component getSelectionAt(MouseEvent e) {
int x = e.getX() - designer.getOuterLeft();
int y = e.getY() - designer.getOuterTop();
for (Component comp : selection) {
//獲取當前組件相對于根組件的相對位置
Rectangle rect = Util.getRelativeBounds(comp);
if ((x >= (rect.x - BOX_SIZE)) && (x <= (rect.x + rect.width + BOX_SIZE)) && (y >= (rect.y - BOX_SIZE)) && (y <= (rect.y + rect.height + BOX_SIZE))) {
return comp;
}
}
return null;
}
/**
* 將所選組件剪切到剪切板上
*/
public void cutSelectedComponent2ClipBoard() {
if (!selection.isEmpty()) {
//清空剪切板
clip_board.clear();
//找到所選擇組件的根
ArrayList<Component> roots = getSelectedRoots();
for (Component root : roots) {
ComponentAdapter adapter = AdapterBus.getComponentAdapter(designer, root);
//添加他們的根組件
clip_board.add(adapter.clone());
}
for (Component component : roots) {
removeBeanFromContainer(component);
}
//觸發事件
fireComponentCut();
//清除被選擇的組件
selection.clear();
designer.repaint();
}
}
private void fireComponentCut() {
DesignerEvent evt = new DesignerEvent(this);
evt.setCutComponents(clip_board);
designer.getEditListenerTable().fireComponentCut(evt);
}
/**
* 獲取當前被選中組件的根列表
*/
public ArrayList<Component> getSelectedRoots() {
ArrayList<Component> roots = new ArrayList<Component>();
for (Component current : selection) {
//如果當前不為根組件,并且當前組件在selection是根組件,則添加該組件
if ((current != designer.getRootComponent()) && isTopContainer(current, selection)) {
roots.add(current);
}
}
return roots;
}
/**
*判斷comonent1在組件列表selection是否是根組件,即頂層容器組件
*/
private boolean isTopContainer(Component component1, ArrayList<Component> selection) {
for (Component component2 : selection) {
//查找每個組件
if ((component1 != component2) && SwingUtilities.isDescendingFrom(component1, component2) && (component2 != designer.getRootComponent())) {
//如果不是組件自身,切component1是component2的子或孫組件,并且component2不是根組件,那么不是頂層容器
return false;
}
}
return true;
}
/**
* 復制當前選中的組件到剪切板
*/
public void copySelectedComponent2ClipBoard() {
if (!selection.isEmpty()) {
//清空剪切板
clip_board.clear();
//獲取被選中組件的根組件
ArrayList<Component> roots = getSelectedRoots();
for (Component root : roots) {
ComponentAdapter adapter = AdapterBus.getComponentAdapter(designer, root);
//放到剪切板中
clip_board.add(adapter.clone());
}
//觸發事件
fireComponentCopyed();
}
}
private void fireComponentCopyed() {
DesignerEvent evt = new DesignerEvent(this);
evt.setCopyedComponents(clip_board);
designer.getEditListenerTable().fireComponentCopyed(evt);
}
/**
* 從剪切板粘帖組件
*/
public void pasteFromClipBoard() {
if (!clip_board.isEmpty()) {
if (!isPasteable()) {
//如果當前被選擇的組件不是容器或者剪切板的內容不可以粘帖
Toolkit.getDefaultToolkit().beep();
} else {
//唯一的容器組件就是粘帖組件的地方
Component root = selection.get(0);
Container container = (Container) root;
for (Component comp : clip_board) {
?? 快捷鍵說明
復制代碼
Ctrl + C
搜索代碼
Ctrl + F
全屏模式
F11
切換主題
Ctrl + Shift + D
顯示快捷鍵
?
增大字號
Ctrl + =
減小字號
Ctrl + -