⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 simplenote.java

📁 mywork是rcp开发的很好的例子
💻 JAVA
字号:
package net.sf.component.simplenote;

import java.io.File;
import java.lang.reflect.Field;
import java.lang.reflect.Method;
import java.util.HashSet;
import java.util.Set;
import java.util.SortedMap;
import java.util.TreeMap;
import java.util.regex.Matcher;
import java.util.regex.Pattern;

import net.sf.util.StringUtil;

import org.eclipse.swt.SWT;
import org.eclipse.swt.custom.PaintObjectEvent;
import org.eclipse.swt.custom.PaintObjectListener;
import org.eclipse.swt.custom.ST;
import org.eclipse.swt.custom.StyleRange;
import org.eclipse.swt.custom.StyledText;
import org.eclipse.swt.dnd.Clipboard;
import org.eclipse.swt.events.VerifyEvent;
import org.eclipse.swt.events.VerifyListener;
import org.eclipse.swt.graphics.GlyphMetrics;
import org.eclipse.swt.graphics.ImageData;
import org.eclipse.swt.graphics.Rectangle;
import org.eclipse.swt.layout.GridData;
import org.eclipse.swt.layout.GridLayout;
import org.eclipse.swt.widgets.Button;
import org.eclipse.swt.widgets.Composite;
import org.eclipse.swt.widgets.Display;
import org.eclipse.swt.widgets.Event;
import org.eclipse.swt.widgets.FileDialog;
import org.eclipse.swt.widgets.Listener;
import org.eclipse.swt.widgets.Shell;

/**
 * 在styledtext的基础构建支持简单图文组合,支持文件附件。
 * 进一步可以利用styledtext的格式功能
 * 存储内容尽量与html规范兼容
 * @author levin
 * @since 20070311
 */
public class SimpleNote extends StyledText {
	private UndoManager undoManager = null;	//undo管理器

	protected SortedMap<Integer,ElementProxy> elements; //文件中图片或文件列表,为图片位置和图片的map
	protected String basePath;	//文件的基准路径
	
	private boolean firstTime;	//是否首次设置内容,如果是,则不校正offset
	
	public SimpleNote(Composite parent, int style) {
		super(parent, style);
		//增加undo支持
		undoManager = new UndoManager(255);
		undoManager.connect(this);

		//增加快捷键
		setKeyBinding('A'|SWT.MOD1, ST.SELECT_ALL);
		setKeyBinding('Z'|SWT.CTRL, UndoManager.UNDO);
		setKeyBinding('Y'|SWT.CTRL, UndoManager.REDO);

		elements=new TreeMap<Integer,ElementProxy>();
		//跟踪offset的娈化
		addVerifyListener(new VerifyListener()  {
			public void verifyText(VerifyEvent e) {
				if((((SimpleNote)e.widget)).isFirstTime()){
					(((SimpleNote)e.widget)).setFirstTime(false);
					return ;
				}
				//校正ElementProxy的位置
				int start = e.start;
				int replaceCharCount = e.end - e.start;
				int newCharCount = e.text.length();
				Set<Integer> set=new HashSet<Integer>(elements.keySet());
				for (int offset : set) {
					if (start <= offset && offset < start + replaceCharCount) {
						ElementProxy proxy=(ElementProxy) elements.remove(offset);
						proxy.dispose();
						if(proxy.src != null){
							//直接删除文件,不能后悔
							new File(basePath,proxy.src).delete();
						}
					}else if (offset >= start) {
						//换key
						ElementProxy proxy=(ElementProxy) elements.remove(offset);
						elements.put(offset +newCharCount - replaceCharCount, proxy);
					}
				}
			}
		});
		addPaintObjectListener(new PaintObjectListener() {
			public void paintObject(PaintObjectEvent event) {
				int start = event.style.start;
				//显示图片或文件
				if(elements.get(start) != null){
					elements.get(start).draw(basePath, event, SimpleNote.this);
				}
			}
		});
	}

	/**
	 * 重载以支持粘接图片及图片文件
	 *@Override
	 */
	public void paste() {
		try {
			Field field=StyledText.class.getDeclaredField("clipboard");
			field.setAccessible(true);
			Clipboard clipboard=(Clipboard) field.get(this);
			//直接粘贴一个图片源
			ImageData imageData=(ImageData) clipboard.getContents(ImageDataTransfer.getInstance());
			if(imageData != null){
				ImageProxy imageProxy = new ImageProxy(imageData);
				addElement(imageProxy);
				return;
			}
			
			//粘贴一个图片或文件
			String[] fileData = (String[])clipboard.getContents(SimpleFileTransfer.getInstance());
			if(fileData !=null){
				for(String file:fileData){
					if(maybeImageFile(file)){
						ImageProxy imageProxy = new ImageProxy(new ImageData(file));
						addElement(imageProxy);
					}else{
						FileProxy fileProxy=new FileProxy(new File(file));
						addElement(fileProxy);
					}
				}
				return;
			}
		} catch (Exception e) {
			e.printStackTrace();
		}
		super.paste();
	}

	public String getText() {
		StringBuffer text = new StringBuffer(super.getText());
		int delta=0;
		for(int offset:elements.keySet()){
			ElementProxy elementProxy = elements.get(offset);
			//还没有保存
			if(elementProxy.src == null){
				elementProxy.save(getBasePath());
			}
			text.replace(offset+delta, offset+delta+1, elementProxy.getHtml());
			delta += elementProxy.getHtml().length() -1;
		}
		return text.toString();
	}

	public void setText(String html) {
		//清除状态
		for(ElementProxy element:elements.values())
			element.dispose();
		elements.clear();
		int delta =0;
		//考虑到同一行可能会同时有图片、文件的组合,采用非贪婪做法
		Pattern p=Pattern.compile("<a.*?>.*?</a>|<img.*?></img>");
		Matcher m=p.matcher(html);
		while(m.find()){
			String group = m.group();
			int offset = m.start();
			ElementProxy elementProxy=ElementProxy.getInstance(group);
			elements.put(offset - delta, elementProxy);
			delta += group.length() -1;
		}
		
		//替换为占位符
		html=html.replaceAll("<a.*?>.*?</a>", new FileProxy().getPlaceholder());
		html=html.replaceAll("<img.*?></img>", new ImageProxy().getPlaceholder());

		//设置为内部格式
		firstTime=true;
		super.setText(html);
		//还需要强制一下,以显示图片
		for(int offset:elements.keySet()){
			showElement(elements.get(offset),offset);
		}
	}

	//追加图文
	public void appendHtml(String html){
		if(html.indexOf("<a") != -1 || html.indexOf("<img") != -1 ){
			String text = this.getText();
			this.setText(text+html);
			this.redraw();
		}else{
			super.append(html);//普通字串
		}
		scrollToLast();
	}
	
	//滚动到最后
	public void scrollToLast(){
		if(getCharCount() < 10 ) return;
		try {
			Rectangle lastBounds = getTextBounds(getCharCount()-5,getCharCount()-1);
			Method m = StyledText.class.getDeclaredMethod("showLocation", Rectangle.class,boolean.class);
			m.setAccessible(true);
			m.invoke(this, lastBounds,true);
		} catch (Exception e) {
			e.printStackTrace();
		} 
	}
	
	//简单通过后缀,判断一下是否图片文件,提高后来用内容判断图片的效率
	public static boolean maybeImageFile(String string) {
		String suffixs=".bmp.jpgjpeg.png.ico.tif.gif";
		if(StringUtil.isNull(string) || string.length() < 4)
			return false;
		if(suffixs.indexOf(string.substring(string.length()-4,string.length()-1).toLowerCase()) != -1)
			return true;
		return false;
	}

	//增加一个非文字元素
	public void addElement(ElementProxy proxy) {
		int offset = getCaretOffset();
		replaceTextRange(offset, 0, proxy.getPlaceholder());
		elements.put(offset, proxy);
		showElement(proxy, offset);
		setCaretOffset(offset+1);
	}

	private void showElement(ElementProxy element, int offset) {
		StyleRange style = new StyleRange ();
		style.start = offset;
		style.length = 1;
		int[] metrics=element.getMetrics();
		style.metrics = new GlyphMetrics(metrics[0],metrics[1],metrics[2]);
		try{
			setStyleRange(style);
		}catch(Exception ex){
			ex.printStackTrace();
		}
	}
	
	public String getBasePath() {
		return basePath;
	}

	public void setBasePath(String basePath) {
		this.basePath = basePath;
	}

	public boolean isFirstTime() {
		return firstTime;
	}

	public void setFirstTime(boolean firstTime) {
		this.firstTime = firstTime;
	}	
	
	public void invokeAction(int action)
	{
	  super.invokeAction(action);

	  switch (action)
	  {
	    case UndoManager.UNDO:
	      undo();
	      break;
	    case UndoManager.REDO:
	      redo();
	      break;
	  }
	}

	private void undo()
	{
	  if (undoManager != null)
	    undoManager.undo();
	}

	private void redo()
	{
	  if (undoManager != null)
	    undoManager.redo();
	  
	}
	@Override
	public void dispose() {
		if(undoManager != null)
			undoManager.disconnect();
		super.dispose();
	}

	//测试实例
	public static void main(String[] args) {
		String text = 
			"This snippet <a href=embed/1115b2306b6.txt width=50 height=17>测试.txt</a>shows how to <a href=embed/1115b2306b6.txt width=50 height=17>测试.txt</a>embed 中华人民共和国images in a StyledText.\n"+
			"Here is one:,\nto add an image from your filesystem to the StyledText"+
			"Use the add button to add an image from your filesystem to the StyledText<a href=embed/1115b2306b6.txt width=50 height=17>测试.txt</a> at the current caret offset.";
		
		final Display display = new Display();
		final Shell shell = new Shell(display);
		shell.setLayout(new GridLayout());
		final SimpleNote note = new SimpleNote(shell, SWT.WRAP | SWT.BORDER|SWT.V_SCROLL);
		note.setText(text);
		note.setBasePath(System.getProperty("java.io.tmpdir"));
		
		note.setLayoutData(new GridData(SWT.FILL, SWT.FILL, true, true));
		Button button = new Button (shell, SWT.PUSH);
		button.setText("Add Image");
		button.setLayoutData(new GridData(SWT.CENTER, SWT.CENTER, false, false));
		button.addListener(SWT.Selection, new Listener() {
			public void handleEvent(Event event) {
				FileDialog dialog = new FileDialog(shell);
				String filename = dialog.open();
				if (filename != null) {
					try {
						if(maybeImageFile(filename))
							note.addElement(new ImageProxy(new ImageData(filename)));
						else
							note.addElement(new FileProxy(new File(filename)));
					} catch (Exception e) {
						e.printStackTrace();
					}
				}				
			}
		});
		shell.setSize(400, 400);
		shell.open();
		while (!shell.isDisposed()) {
			if (!display.readAndDispatch())
				display.sleep();
		}
		display.dispose();
	}

}

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -