source: trunk/src/org/expeditee/agents/Format.java@ 919

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

Added license headers to all files, added full GPL3 license file, moved license header generator script to dev/bin/scripts

File size: 6.8 KB
Line 
1/**
2 * Format.java
3 * Copyright (C) 2010 New Zealand Digital Library, http://expeditee.org
4 *
5 * This program is free software: you can redistribute it and/or modify
6 * it under the terms of the GNU General Public License as published by
7 * the Free Software Foundation, either version 3 of the License, or
8 * (at your option) any later version.
9 *
10 * This program is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 * GNU General Public License for more details.
14 *
15 * You should have received a copy of the GNU General Public License
16 * along with this program. If not, see <http://www.gnu.org/licenses/>.
17 */
18
19package org.expeditee.agents;
20
21import java.util.ArrayList;
22import java.util.Collection;
23import java.util.Collections;
24import java.util.Comparator;
25import java.util.HashSet;
26import java.util.List;
27
28import org.expeditee.gui.Frame;
29import org.expeditee.gui.FrameGraphics;
30import org.expeditee.gui.FrameUtils;
31import org.expeditee.items.Item;
32import org.expeditee.items.Text;
33
34/**
35 * A simple formatting agent that aligns all non-annotation Items on the given
36 * Frame by the X and Y axis of the first Item on the Frame. This agent
37 * separates the items into columns, the actual alignment is done by
38 * FrameUtils.Align()
39 *
40 * @author jdm18
41 *
42 */
43public class Format extends DefaultAgent {
44 // whether the Items could be formatted successfully
45 private boolean _success = true;
46
47 // adjustmen from the default format spacing
48 private int _adjust = 0;
49
50 public Format() {
51 super();
52 }
53
54 public Format(String param) {
55 try {
56 if (param.startsWith("+"))
57 param = param.substring(1);
58 _adjust = Integer.parseInt(param);
59 } catch (Exception e) {
60 e.printStackTrace();
61 }
62 }
63
64 @Override
65 public Frame process(Frame start) {
66 // TODO What will happen if user runs the SIMPLE form of this...
67 // Does format box need to be disabled?!?!
68 // Check the position of the cursor and only format stuff inside the
69 // same box as the cursor
70 Collection<Text> itemsToFormat = getItemsToFormat(start);
71
72 List<Item> changedItems = new ArrayList<Item>();
73
74 ArrayList<Item> columnHeads = new ArrayList<Item>();
75
76 ArrayList<ArrayList<Text>> columns = new ArrayList<ArrayList<Text>>();
77
78 for (Text t : itemsToFormat) {
79 int col = findColumn(columnHeads, t);
80 // if this is the head of a new column
81 if (col < 0) {
82 columnHeads.add(t);
83 columns.add(new ArrayList<Text>());
84 // otherwise the column for this item has already been
85 // found set the column to be the one we just added...
86 col = columns.size() - 1;
87 } else
88 columns.get(col).add(t);
89 }
90
91 // check for empty columns
92 int[] clear = new int[columnHeads.size()];
93 for (int i = 0; i < columns.size(); i++)
94 clear[i] = columns.get(i).size();
95
96 // remove empty columns
97 for (int i = (clear.length - 1); i >= 0; i--)
98 if (clear[i] == 0) {
99 columns.remove(i);
100 columnHeads.remove(i);
101 }
102
103 // if there are no columns to align, we are done
104 if (columns.size() == 0)
105 return null;
106
107 // sort the column heads by X position
108 Collections.sort(columnHeads, new Comparator<Item>() {
109 public int compare(Item o1, Item o2) {
110 return o1.getX() - o2.getX();
111 }
112
113 });
114
115 // sort lists by their X axis
116 Collections.sort(columns, new Comparator<ArrayList<Text>>() {
117 public int compare(ArrayList<Text> o1, ArrayList<Text> o2) {
118 if (o2.size() == 0)
119 return -10;
120
121 if (o1.size() == 0)
122 return 10;
123
124 Item i1 = o1.get(0);
125 Item i2 = o2.get(0);
126
127 return (i1.getX() - i2.getX());
128 }
129
130 });
131
132 int res = FrameUtils.Align(columns.get(0), true, _adjust);
133 _success = _success && (res >= 0);
134
135 for (int i = 0; i < columns.size() - 1; i++) {
136 List<Text> list = columns.get(i);
137
138 int maxX = 0;
139 int maxY = 0;
140 for (Item it : list) {
141 maxX = Math.max(maxX, it.getX() + it.getBoundsWidth());
142 maxY = Math.max(maxY, it.getY() + it.getBoundsHeight());
143 }
144
145 int xCheck = maxX;
146 for (Item it : columns.get(i + 1))
147 xCheck = Math.max(xCheck, maxX
148 + /* item.getX() + */it.getBoundsWidth());
149
150 if (xCheck < FrameGraphics.getMaxSize().width) {
151 Item columnHead = columnHeads.get(i + 1);
152 if (columnHead.getX() < maxX && columnHead.getY() < maxY) {
153 if(columnHead.getX() != maxX && !changedItems.contains(columnHead)) {
154 Item copy = columnHead.copy();
155 copy.setID(columnHead.getID());
156 changedItems.add(copy);
157 }
158 columnHead.setX(maxX);
159 }
160
161 for (Item it : columns.get(i + 1)) {
162 if (it.getX() < maxX && it.getY() < maxY) {
163 if(it.getX() != maxX && !changedItems.contains(it)) {
164 Item copy = it.copy();
165 copy.setID(it.getID());
166 changedItems.add(copy);
167 }
168 it.setX(maxX);
169 }
170 }
171 }
172
173 res = FrameUtils.Align(columns.get(i + 1), true, _adjust, changedItems);
174 _success = _success && (res >= 0);
175 }
176
177 // align all the separate columns
178 /*
179 * for(ArrayList<Item> l : columns){ int res = FrameUtils.Align(l,
180 * true); _success = _success && (res >= 0); }
181 */
182 start.setChanged(true);
183 start.addToUndoMove(changedItems);
184 FrameGraphics.requestRefresh(true);
185 return null;
186 }
187
188 /**
189 * Finds which column contains the given Item, and returns the index to the
190 * column in the start & end lists. Returns -1 if no column is found that
191 * contains the given Item.
192 *
193 * @param toFind
194 * The Item to determine the correct column for
195 * @return The index of the column in the lists, or -1 if no column is found
196 */
197 private int findColumn(ArrayList<Item> columnHeads, Item toFind) {
198 for (Item top : columnHeads)
199 if (FrameUtils.inSameColumn(top, toFind))
200 return columnHeads.indexOf(top);
201
202 return -1;
203 }
204
205 @Override
206 protected void finalise(Frame start) {
207 if (_success)
208 overwriteMessage("Formatting complete.");
209 }
210
211 @Override
212 protected void message(String message) {
213 }
214
215 @Override
216 protected void overwriteMessage(String message) {
217 }
218
219 /**
220 * Gets all the items that need to be formatted. If the user clicks in
221 * freeSpace these are all items not enclosed by a rectangle. If the user is
222 * formatting the items in a rectangle this is all the items in the
223 * rectangle.
224 *
225 * @param start
226 */
227 protected Collection<Text> getItemsToFormat(Frame start) {
228 Collection<Text> itemsToFormat = FrameUtils.getCurrentTextItems();
229
230 // If the cursor is not inside a box...
231 if (itemsToFormat.size() < 1) {
232 // Add all the items that are in free space
233 itemsToFormat = start.getBodyTextItems(true);
234 // Remove all the enclosed items
235 Collection<Item> seen = new HashSet<Item>();
236 for (Item i : start.getVisibleItems()) {
237 if (!seen.contains(i) && i.isEnclosed()) {
238 seen.addAll(i.getEnclosingDots());
239 itemsToFormat.removeAll(i.getEnclosedItems());
240 }
241 }
242 }
243 return itemsToFormat;
244 }
245
246}
Note: See TracBrowser for help on using the repository browser.