📄 draw.java
字号:
package draw;
import java.awt.Color;
import java.awt.Container;
import java.beans.PropertyVetoException;
import java.io.File;
import java.util.Iterator;
import java.util.Vector;
import javax.swing.JDesktopPane;
import javax.swing.JFileChooser;
import javax.swing.JInternalFrame;
import javax.swing.JPanel;
import javax.swing.event.InternalFrameEvent;
import javax.swing.event.InternalFrameListener;
import javax.swing.filechooser.FileFilter;
import draw.figuare.AbstractFiguare;
import app.Application;
import app.action.Actions;
/**
* 画板,在程序中充当画布View的管理者。<br/> 它从画笔工具PaintPane获得当前用户选中的画笔工具shape,
* 并更新当前所有画布View的画笔工具。<br/> Draw负责新建、删除、保存画布。<br/> 注:网络的同步是针对一个画布View的,而不是Draw。
*
* @author Thihy
*
*/
public class Draw implements InternalFrameListener {
protected Vector<View> views;// 存储当前所有画布
protected View currentView;// 必须是VIEWS的一员
protected JDesktopPane contentPane;// 画板的主容器
protected JPanel littleMenuPane;// 小型菜单,在菜单栏的右侧显示,当最大化之后会显示出来
protected Application app; // 所在的主窗口
protected static int viewNum=0;
// 一些颜色
protected Color strokeColor = Color.black;
protected Color fillColor = Color.white;
protected int paintTool = AbstractFiguare.ARROW;
protected JFileChooser fileChooser;
protected AbstractFiguare clip=null;//剪切复制用
/**
* 初始化
*
* @param parent
* 所在的主窗口
*/
public Draw(Application parent) {
views = new Vector<View>();
contentPane = new JDesktopPane();
contentPane.setBackground(Color.lightGray);
this.app = parent;
currentView = null;
littleMenuPane = app.getMenuPane().creatPanel(this);
fileChooser = creatFileChooser();
updateActionEnable();
}
/**
* 获取当前窗口的内容面板。<br/> 不应该向里面添加任何组件,因为它 是有程序Draw来布置View画布的一个 容器。
*
* @return 内容面板
*/
public Container getContentPane() {
return contentPane;
}
/**
* 打开一个文件
*/
public void OpenView() {
int ans = fileChooser.showOpenDialog(app);
if (ans == JFileChooser.APPROVE_OPTION) {
File file = fileChooser.getSelectedFile();
if (file.isFile() && file.canRead()) {
View view = creatView(file.getName());
if (view != null) {
view.load(file);
} else {
// do nothing
}
}
}
}
/**
* 创建并返回一个文件选择器 会建立一个文件过滤器
*
* @return 文件选择器
*/
private JFileChooser creatFileChooser() {
JFileChooser filechooser = new JFileChooser();
filechooser.setAcceptAllFileFilterUsed(true);
// 文件过滤器
FileFilter filter = new FileFilter() {
@Override
public String getDescription() {
return "Paint 文件 (*." + Application.viewfileSuffix + ")";
}
@Override
public boolean accept(File f) {
String fileName = f.getName();
if (f.isDirectory())
return true;
if (fileName.matches(".*\\." + Application.viewfileSuffix)) { // 文件以pnt后缀结束
return true;
}
return false;
}
};
filechooser.setFileFilter(filter);
filechooser.setFileHidingEnabled(true);
filechooser.setMultiSelectionEnabled(false);
return filechooser;
}
/**
* 返回一个文件选择器
*
* @return 文件选择器
*/
public JFileChooser getFileChooser() {
return fileChooser;
}
/**
* 还原画布
*/
public void restoreAllViews() {
Iterator<View> iter = views.iterator();
while (iter.hasNext()) {
View view = iter.next();
InnerFrame i = (InnerFrame) view.getViewPort();
try {
i.setMaximum(false);
} catch (PropertyVetoException ex) {
ex.printStackTrace();
}
i.showNorthPanel();
}
updateActionEnable();
}
/**
* 新建一个画布,采用默认名称:未标题 - 标号
*
* @return 新建的画布
*/
public View creatView() {
return creatView(null);
}
/**
* 创建一个新的画布, 并将此画布设置为正在使用的画布
*/
public View creatView(String name) {
++viewNum;
if(name==null)
name="未标题 - " + (viewNum);
View newView = new View(name, this, viewNum);
JInternalFrame viewPort = newView.getViewPort();
if (viewPort == null) {
if (Application.DEBUG > 0) {
System.out.println("在Draw调用View:名称(" + newView.getName() + "),"
+ "ID(" + viewNum + ")的getViewPort时发生了意外:返回了一个NULL指针");
}
return null;
}
contentPane.add(viewPort, 0);// 在内容面板中显示。
/*
* 每次向下向右移动20px 如果到达边界,则停止移动 注意:缩小主窗口后再放大,可能位置不连贯。
*/
int px = Math.min(20 * viewNum, contentPane.getWidth() - viewPort.getWidth()
- 1);
int py = Math.min(20 * viewNum, contentPane.getHeight()
- viewPort.getHeight() - 1);
px = Math.max(px, 0);
py = Math.max(py, 0);
viewPort.setLocation(px, py);
try {
if (currentView != null) {
JInternalFrame currentViewPort = currentView.getViewPort();
if (currentViewPort.isMaximum() && !currentViewPort.isIcon()) {
viewPort.setMaximum(true);
}
} else {
viewPort.setMaximum(true);
}
} catch (PropertyVetoException e) {
if (Application.DEBUG > 7)
e.printStackTrace();
}
views.add(newView);
setCurrentView(viewNum);
newView.setStrokeColor(strokeColor);
newView.setFillColor(fillColor);
newView.setPaintTool(paintTool);
updateActionEnable();
return newView;
}
// 获取小型菜单栏,由InnerFrame调用
public JPanel getLittleMenuPane() {
return littleMenuPane;
}
/**
* 设置当前用户选择的图形。 通过其ID指定,这些ID在AbstractFiguare类中定义
*
* @param figuareID
* 图形的ID。
*/
public void setPaintTool(int figuareID) {
paintTool = figuareID;
int size = views.size();
for (int i = 0; i < size; ++i) {
views.elementAt(i).setPaintTool(figuareID);
}
}
/**
* 设置当前选中图形的线形颜色
*
* @param color
* 线形颜色
*/
public void setStrokeColor(Color color) {
strokeColor = color;
int size = views.size();
for (int i = 0; i < size; ++i) {
views.elementAt(i).setStrokeColor(color);
}
}
/**
* 设置当前选中图形的填充颜色
*
* @param color
* 线形颜色
*/
public void setFillColor(Color color) {
fillColor = color;
int size = views.size();
for (int i = 0; i < size; ++i) {
views.elementAt(i).setFillColor(color);
}
}
/**
* 剪切当前窗口中的当前图形
*/
public void cutCurrentFiguare() {
if(currentView==null)return;
AbstractFiguare tClip;
if((tClip=currentView.getCanvas().cutFiguare())!=null){
clip=tClip;
}
}
/**
* 复制当前窗口中的当前图形
*/
public void copyCurrentFiguare() {
if(currentView==null)return;
AbstractFiguare tClip;
if((tClip=currentView.getCanvas().copyFiguare())!=null){
clip=tClip;
}
}
/**
* 剪切当前窗口中的当前图形
*/
public void pasteCurrentFiguare() {
if(currentView==null||clip==null)return;
AbstractFiguare tClip;
currentView.getCanvas().pasteFiguare((AbstractFiguare)clip.clone());
}
/**
* 获取指定ID的画布
*
* @param id
* 指定的ID
* @return 指定ID的画布
*/
private View getViewWithId(int id) {
int size = views.size();
View newCurrentView = null;
for (int i = 0; i < size; ++i) {
if (views.elementAt(i).viewId == id) {
newCurrentView = views.elementAt(i);
break;
}
}
return newCurrentView;
}
/**
* 设置当前画布为指定Id的画布
*/
public void setCurrentView(int id) {
View newCurrentView = getViewWithId(id);
int size = views.size();
if (newCurrentView == null)
return;
for (int i = 0; i < size; ++i) {
if (views.elementAt(i).viewId == id) {
newCurrentView = views.elementAt(i);
break;
}
}
if (newCurrentView == null)
return;
if (currentView == newCurrentView)
return;
if (currentView != null) {
// 将旧的使用画布置于后面
currentView.getViewPort().moveToBack();
}
currentView = newCurrentView;
// 将当前画布提前
currentView.getViewPort().moveToFront();
updateActionEnable();
}
/**
* 获取当前画布
*/
public View getCurrentView() {
return currentView;
}
/**
* 关闭当前正在使用的画布
*/
public boolean closeCurrentView() {
if (currentView == null)
return false;
if (currentView.close()) {// 如果当前画布成功关闭
views.remove(currentView);
// 设置当前使用画布
if (views.size() > 0) {
currentView = views.lastElement();
currentView.getViewPort().moveToFront();
} else {
currentView = null;
}
updateActionEnable();// 更新所有的Action
return true;
}
updateActionEnable();// 更新所有的Action
return false;
}
/**
* 更新所有的Action 主要是激活或禁用一些菜单项等
*/
public void updateActionEnable() {
boolean existView = (views.size() > 0), hasCurrentView = (currentView != null);
Actions.saveAction.setEnabled(existView && hasCurrentView);
Actions.saveAsAction.setEnabled(existView && hasCurrentView);
Actions.geneteImageAction.setEnabled(existView && hasCurrentView);
Actions.closeAction.setEnabled(existView && hasCurrentView);
Actions.closeAllAction.setEnabled(existView);
if (currentView != null) {
Actions.becomeServerAction.setEnabled(!currentView.IsConnected());
Actions.unConnectServerAction.setEnabled(currentView.IsConnected());
}
// 最大化画布之后显示小型菜单栏,且主窗口的标题设置为当前画布的标题
if (currentView != null && currentView.getViewPort().isMaximum()) {
littleMenuPane.setVisible(true);
app.setTitle(currentView.getViewPort().getTitle() + " - "
+ Application.APPNAME);
} else {
littleMenuPane.setVisible(false);
app.setTitle(Application.APPNAME);
}
}
/**
* 关闭所有的画布
*/
public boolean closeAllViews() {
while (views.size() > 0) {
View view = views.lastElement();
if (view.close()) {
views.remove(view);
} else {
return false;
}
}
return true;
}
/**
* 保存当前正在使用的画布
*/
public void saveCurrentView() {
if (currentView != null)
currentView.save();
}
public void saveCurrentViewAs() {
if (currentView != null)
currentView.saveAs();
}
/**
* 保存所有的画布
*/
public void saveAllView() {
for (View view : views) {
view.save();
}
}
/**
* 获取当前窗口中的所有画布
*
* @return 所有画布的向量表
*/
public Vector<View> getViews() {
return views;
}
/**
* 新建一个服务器
*/
public void newServer() {
currentView=creatView();
if (currentView==null || !becomeServer()) {// 成为服务器失败
// 删除这个画布
closeCurrentView();
}
}
/**
* 将当前画布设置为服务器
*
* @return 成功成为服务器则返回真
*/
public boolean becomeServer() {
if (currentView == null)
return false;
if (currentView.creatServer()) {
updateActionEnable();
return true;
}
return false;
}
/**
* 新建一个客户端
*/
public void newClient() {
currentView=creatView();
if (currentView==null || !currentView.creatClient()) {// 成为客户端失败
// 删除这个画布
updateActionEnable();
closeCurrentView();
}
}
/**
* 断开连接
*/
public void unConnectServer() {
if (currentView == null)
return;
currentView.unConnectServer();
}
// --------------------------------------------------------
// 以下是内部框架的监听器,主要用于关闭
@Override
public void internalFrameActivated(InternalFrameEvent e) {
int id = (Integer) e.getInternalFrame().getClientProperty("ID");
setCurrentView(id);
}
@Override
public void internalFrameClosed(InternalFrameEvent e) {
}
@Override
public void internalFrameClosing(InternalFrameEvent e) {
int id = (Integer) e.getInternalFrame().getClientProperty("ID");
if (getViewWithId(id) != null) {
View view = getViewWithId(id) ;
if (view.close()) {
views.remove(view);
}
updateActionEnable();
}
}
@Override
public void internalFrameDeactivated(InternalFrameEvent e) {
}
@Override
public void internalFrameDeiconified(InternalFrameEvent e) {
}
@Override
public void internalFrameIconified(InternalFrameEvent e) {
}
@Override
public void internalFrameOpened(InternalFrameEvent e) {
}
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -