source: trunk/src/org/expeditee/io/ItemSelection.java@ 821

Last change on this file since 821 was 740, checked in by jts21, 10 years ago

Modify the undo stack to use a stack of List rather than a stack of connected items (easier to understand, and since we have to parse it linearly anyways it's not any slower)
Also started making other stuff undo-able, so far vertical auto-format can be undone, probably pretty inefficient (every time I add to the list of items modified by the vertical format I have to walk the entire list of modified items to make sure I don't add it multiple times).
I think it might be a good idea to add a redo functionality as well (simple enough to do, but we need a key/mouse binding for it)
Also modified copy/pasting to fix a bug where cutting a point on a shape would leave the rest of the shape on the screen (and broken). Now it just takes the whole shape (again, this is done inefficiently since for every item we walk the entire list of known items to see if we've seen it before. IDK if that will need to be rewritten to speed it up somehow).

File size: 7.1 KB
Line 
1package org.expeditee.io;
2
3
4import java.awt.Image;
5import java.awt.Toolkit;
6import java.awt.datatransfer.Clipboard;
7import java.awt.datatransfer.DataFlavor;
8import java.awt.datatransfer.Transferable;
9import java.awt.datatransfer.UnsupportedFlavorException;
10import java.awt.image.BufferedImage;
11import java.io.File;
12import java.io.IOException;
13import java.io.Serializable;
14import java.util.ArrayList;
15import java.util.Arrays;
16import java.util.List;
17
18import javax.imageio.ImageIO;
19
20import org.expeditee.gui.DisplayIO;
21import org.expeditee.gui.FrameGraphics;
22import org.expeditee.gui.FrameIO;
23import org.expeditee.gui.FrameMouseActions;
24import org.expeditee.gui.FreeItems;
25import org.expeditee.gui.MessageBay;
26import org.expeditee.items.Item;
27import org.expeditee.items.ItemUtils;
28import org.expeditee.items.Picture;
29import org.expeditee.items.StringUtils;
30import org.expeditee.items.Text;
31
32/**
33 * Allows item data (text) and metadata (position, shapes, etc) to be stored on the clipboard
34 *
35 * @author jts21
36 */
37public class ItemSelection implements Transferable {
38
39 /**
40 * Class used for storing data which can be used to reconstruct expeditee objects from the clipboard
41 * Stores data as a String containing .exp save data
42 */
43 public static final class ExpDataHandler implements Serializable {
44
45 private static final long serialVersionUID = 1L;
46
47 // whether this should be automatically picked up
48 public boolean autoPaste = true;
49
50 // exp save data
51 public String items;
52 }
53
54 public static final DataFlavor expDataFlavor = new DataFlavor(ExpDataHandler.class, "expDataHandler");
55
56 private static final int STRING = 0;
57 private static final int IMAGE = 1;
58 private static final int EXP_DATA = 2;
59
60 private static final DataFlavor[] flavors = {
61 DataFlavor.stringFlavor,
62 DataFlavor.imageFlavor,
63 expDataFlavor
64 };
65
66 private String data;
67 private Image image;
68 private ExpDataHandler expData;
69
70 public ItemSelection(String data, Image image, ExpDataHandler expData) {
71 this.data = data;
72 this.image = image;
73 this.expData = expData;
74 }
75
76 @Override
77 public DataFlavor[] getTransferDataFlavors() {
78 return (DataFlavor[])flavors.clone();
79 }
80
81 @Override
82 public boolean isDataFlavorSupported(DataFlavor flavor) {
83 for (int i = 0; i < flavors.length; i++) {
84 if (flavor.equals(flavors[i])) {
85 return true;
86 }
87 }
88 return false;
89 }
90
91 @Override
92 public Object getTransferData(DataFlavor flavor)
93 throws UnsupportedFlavorException, IOException {
94 if (flavor.equals(flavors[STRING])) {
95 return (Object)data;
96 } else if (flavor.equals(flavors[IMAGE])) {
97 return (Object)image;
98 } else if (flavor.equals(flavors[EXP_DATA])) {
99 return (Object)expData;
100 } else {
101 throw new UnsupportedFlavorException(flavor);
102 }
103 }
104
105 private static List<Item> getAllToCopy() {
106 List<Item> tmp = new ArrayList<Item>(FreeItems.getInstance());
107 List<Item> toCopy = new ArrayList<Item>(tmp);
108 for(Item i : tmp) {
109 for(Item c : i.getAllConnected()) {
110 if(! toCopy.contains(c)) {
111 toCopy.add(c);
112 FrameMouseActions.pickup(c);
113 }
114 }
115 }
116 return toCopy;
117 }
118
119 public static void cut() {
120
121 List<Item> toCopy = getAllToCopy();
122
123 copy(toCopy);
124
125 // remove the items attached to the cursor
126 DisplayIO.getCurrentFrame().removeAllItems(toCopy);
127 FreeItems.getInstance().clear();
128
129 FrameGraphics.refresh(false);
130 }
131
132 public static void copyClone() {
133
134 copy(ItemUtils.CopyItems(getAllToCopy()));
135
136 }
137
138 /**
139 * Copies whatever items are attached to the mouse to the clipboard
140 */
141 private static void copy(List<Item> items) {
142 if(items.size() <= 0) {
143 return;
144 }
145
146 StringBuilder clipboardText = new StringBuilder();
147 ExpDataHandler expData = new ExpDataHandler();
148 Image image = null;
149
150 // get plaintext
151 for(Item i : items) {
152 if(i instanceof Text) {
153 clipboardText.append(((Text)i).getText());
154 clipboardText.append("\n\n");
155 }
156 if(i instanceof Picture) {
157 // TODO: merge multiple images if necessary
158 image = ((Picture)i).getImage();
159 }
160 }
161
162 // get expeditee item data
163 ExpClipWriter ecw = new ExpClipWriter(FrameMouseActions.getX(), FrameMouseActions.getY());
164 try {
165 ecw.output(items);
166 } catch (IOException e1) {
167 e1.printStackTrace();
168 }
169 expData.items = ecw.getFileContents();
170 // System.out.println(expData.items);
171
172 // write out to clipboard
173 ItemSelection selection = new ItemSelection(clipboardText.toString(), image, expData);
174 Toolkit.getDefaultToolkit().getSystemClipboard().setContents(selection, null);
175 }
176
177 /**
178 * Generates items from the clipboard data
179 * TODO: Enable pasting raw image data (would require saving the data as an image file and generating a Text item pointing to it)
180 */
181 public static void paste() {
182 if(FreeItems.itemsAttachedToCursor()) {
183 MessageBay.displayMessage("Drop any items being carried on the cursor, then try pasting again");
184 return;
185 }
186 String type = "";
187 FreeItems f = FreeItems.getInstance();
188 Clipboard c = Toolkit.getDefaultToolkit().getSystemClipboard();
189 Transferable content = c.getContents(null);
190 try {
191 if(content.isDataFlavorSupported(ItemSelection.expDataFlavor)) { // Expeditee data
192 type = "Expeditee ";
193 ExpDataHandler expData = (ExpDataHandler)content.getTransferData(ItemSelection.expDataFlavor);
194 if(expData != null) {
195 List<Item> items = new ExpClipReader(FrameMouseActions.getX(), FrameMouseActions.getY()).read(expData.items);
196 // generate new IDs and pickup
197 FrameMouseActions.pickup(ItemUtils.CopyItems(items));
198 }
199 } else if(content.isDataFlavorSupported(DataFlavor.imageFlavor)) { // Image data
200 // System.out.println("IZ PIKTUR");
201 type = "Image ";
202 BufferedImage img = (BufferedImage)content.getTransferData(DataFlavor.imageFlavor);
203 int hashcode = Arrays.hashCode(img.getData().getPixels(0, 0, img.getWidth(), img.getHeight(), (int[])null));
204 File out = new File(FrameIO.IMAGES_PATH + Integer.toHexString(hashcode) + ".png");
205 out.mkdirs();
206 ImageIO.write(img, "png", out);
207 Text item = DisplayIO.getCurrentFrame().createNewText("@i: " + out.getPath());
208 f.add(item);
209 ExpClipReader.updateItems(f);
210 } else if(content.isDataFlavorSupported(DataFlavor.stringFlavor)) { // Plain text
211 type = "Plain Text ";
212 String clip = ((String) content.getTransferData(DataFlavor.stringFlavor));
213 // Covert the line separator char when pasting in
214 // windows (\r\n) or max (\r)
215 clip = StringUtils.convertNewLineChars(clip);
216 // blank line is an item separator
217 String[] items = clip.split("\n\n");
218 Item item, prevItem = null;
219 for(int i = 0; i < items.length; i++) {
220 // System.out.println(items[i]);
221 // System.out.println("Created item from string");
222 item = DisplayIO.getCurrentFrame().createNewText(items[i]);
223 if(prevItem != null){
224 item.setY(prevItem.getY() + prevItem.getBoundsHeight());
225 }
226 f.add(item);
227 prevItem = item;
228 }
229 } /* else if {
230 // Next handler
231 } */
232 } catch (Exception e) {
233 System.out.println("Failed to load " + type + "data");
234 e.printStackTrace();
235 }
236 }
237
238}
Note: See TracBrowser for help on using the repository browser.