source: trunk/src/org/expeditee/gui/FrameCreator.java@ 1532

Last change on this file since 1532 was 1532, checked in by bnemhaus, 4 years ago

New feature: when creating a frameset, if the item being used is linked and you hold shift, it will use the items on the linked frame to populate the zero frame of the new frameset

File size: 11.7 KB
Line 
1/**
2 * FrameCreator.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.gui;
20
21import java.io.File;
22import java.io.IOException;
23import java.nio.file.Files;
24import java.nio.file.Path;
25import java.nio.file.Paths;
26import java.util.Collection;
27import java.util.Comparator;
28import java.util.LinkedList;
29import java.util.List;
30import java.util.Optional;
31
32import org.expeditee.agents.ExistingFramesetException;
33import org.expeditee.agents.InvalidFramesetNameException;
34import org.expeditee.core.Colour;
35import org.expeditee.items.Item;
36import org.expeditee.items.Text;
37
38public class FrameCreator {
39
40 public static final int INDENT_FROM_TITLE = 20;
41
42 private int START_Y;
43
44 private int START_X;
45
46 private Frame _current = null;
47
48 private int _lastX;
49
50 private int _maxX = 0;
51
52 private int _lastY;
53
54 // Master copy of next & previous links
55 private Item _Mnext;
56
57 private Item _Mprev;
58
59 private Item _Mfirst;
60
61 private Frame _firstFrame;
62
63 private boolean _multiColumn;
64
65 public enum ExistingFramesetOptions {
66 /**
67 * Do not attempt to use any existing frames in specified framesets.
68 */
69 AppendSegregatedFrames,
70 /**
71 * Override any existing frames in specified framesets.
72 */
73 OverrideExistingFrames,
74 /**
75 * Use the existing frames in the framesets to reobtain what the state of the
76 * FrameCreator should be.
77 */
78 AppendAfterLastItem
79 }
80
81 private final List<Frame> framesCreated = new LinkedList<Frame>();
82
83 private String encryptionLabel;
84
85 public FrameCreator(String frameTitle) {
86 this(DisplayController.getCurrentFrame().getFramesetName(), DisplayController.getCurrentFrame().getPath(),
87 frameTitle, ExistingFramesetOptions.AppendSegregatedFrames, false, null);
88 }
89
90 public FrameCreator(String framesetName, String path, String frameTitle, ExistingFramesetOptions establishState, boolean multiColumn, String encryptionLabel) {
91 this.encryptionLabel = encryptionLabel;
92 switch (establishState) {
93 case OverrideExistingFrames:
94 try {
95 FrameIO.SuspendCache();
96 Path framesetDir = Files.createTempDirectory("temporaryExpediteeFrameset");
97 initialise(framesetName, framesetDir.toAbsolutePath(), frameTitle, multiColumn);
98 FrameIO.EnableCache();
99 FrameIO.deleteFrameset(framesetName);
100 FrameIO.moveFrameset(framesetName, framesetDir.toAbsolutePath().toString() + File.separator, path, true);
101 _current.setPath(path);
102 framesetDir.toFile().deleteOnExit();
103 } catch (IOException e) {
104 e.printStackTrace();
105 }
106 break;
107 case AppendSegregatedFrames:
108 initialise(framesetName, Paths.get(path), frameTitle, multiColumn);
109 break;
110 case AppendAfterLastItem:
111 initialiseReobtainState(framesetName, Paths.get(path), frameTitle, multiColumn);
112 break;
113 }
114 }
115
116 private void initialiseReobtainState(String framesetName, Path path, String frameTitle, boolean multiColumn) {
117 _multiColumn = multiColumn;
118 _Mnext = createButton("@Next", null, null, 10, 15);
119 _Mprev = createButton("@Previous", null, null, _Mnext.getBoundsWidth() + _Mnext.getAnchorRight() + 20, 15);
120 _Mfirst = createButton("@First", null, null, _Mprev.getBoundsWidth() + _Mprev.getAnchorRight() + 20, 15);
121
122 int lastNumber = FrameIO.getLastNumber(framesetName);
123 for (int i = 1; i <= lastNumber; i++) {
124 Frame frame = FrameIO.LoadFrame(framesetName + i, path.toAbsolutePath().toString() + File.separator);
125 this.framesCreated.add(frame);
126 }
127 if (this.framesCreated.isEmpty()) {
128 initialise(framesetName, path, frameTitle, multiColumn);
129 return;
130 }
131 _firstFrame = this.framesCreated.get(0);
132 _current = this.framesCreated.get(this.framesCreated.size() - 1);
133
134 Collection<Text> allExistingTextItems = _current.getTextItems();
135 allExistingTextItems.remove(_Mfirst);
136 allExistingTextItems.remove(_Mnext);
137 allExistingTextItems.remove(_Mprev);
138 Optional<Text> maxByY = allExistingTextItems.stream().max(new Comparator<Text>() {
139 @Override
140 public int compare(Text t1, Text t2) {
141 return t1.getY() - t2.getY();
142 }
143 });
144 if (maxByY.isPresent()) {
145 Text lowest = maxByY.get();
146 _lastY = lowest.getY() + lowest.getBoundsHeight() / 2;
147 }
148 Optional<Text> maxByX = allExistingTextItems.stream().max(new Comparator<Text>() {
149 @Override
150 public int compare(Text t1, Text t2) {
151 return t1.getX() - t2.getX();
152 }
153 });
154 if (maxByX.isPresent()) {
155 Text furthest = maxByX.get();
156 _lastX = furthest.getX();
157 }
158 }
159
160 private void initialise(String framesetName, Path path, String frameTitle, boolean multiColumn) {
161 _multiColumn = multiColumn;
162 _Mnext = createButton("@Next", null, null, 10, 15);
163 _Mprev = createButton("@Previous", null, null, _Mnext.getBoundsWidth() + _Mnext.getAnchorRight() + 20, 15);
164 _Mfirst = createButton("@First", null, null, _Mprev.getBoundsWidth() + _Mprev.getAnchorRight() + 20, 15);
165
166 try {
167 Frame toUse;
168 if (FrameIO.canAccessFrameset(framesetName, path)) {
169 toUse = FrameIO.CreateFrame(framesetName, frameTitle, null);
170 } else {
171 toUse = FrameIO.CreateFrameset(framesetName, path.toAbsolutePath().toString() + File.separator, true, null);
172 }
173
174 if (encryptionLabel != null && encryptionLabel.length() > 0) {
175 toUse.setFrameEncryptionLabel(encryptionLabel);
176 }
177
178 this.framesCreated.add(toUse);
179 resetGlobals(toUse);
180 _firstFrame = toUse;
181 } catch (InvalidFramesetNameException e) {
182 e.printStackTrace();
183 } catch (ExistingFramesetException e) {
184 // This should never happen as we are allowing for an override of existing frameset.
185 }
186 }
187
188 /**
189 * Creates a text item that looks like a clickable button.
190 *
191 * @param text
192 * the caption for the button
193 * @param x
194 * the x position for the button. Null if the button is anchored to
195 * the right of the screen.
196 * @param y
197 * the y position for the button. Null if the button is anchored to
198 * the bottom of the screen.
199 * @param right
200 * the distance the button is anchored from the right of this screen.
201 * Null if an absolute position is used.
202 * @param bottom
203 * the distance the button is to be anchored from the bottom of the
204 * screen. Null if the button is given an absolute position.
205 * @return the newly created button.
206 */
207 public static Item createButton(String text, Integer x, Integer y, Integer right, Integer bottom) {
208 Text button = new Text(text);
209
210 button.setBackgroundColor(Colour.LIGHT_GREY);
211 button.setBorderColor(Colour.DARK_GREY);
212 button.setThickness(2.0F);
213 if (bottom != null)
214 button.setAnchorBottom(bottom);
215 if (x != null)
216 button.setX(x);
217 if (right != null)
218 button.setAnchorRight(right);
219 if (y != null)
220 button.setY(y);
221
222 button.invalidateBounds();
223
224 return button;
225 }
226
227 public String getName() {
228 return _firstFrame.getName();
229 }
230
231 /**
232 * Creates the next frame in the frameset, with a previous button already added
233 * and linked to the last frame. _current then gets updated to point at the
234 * newly created Frame, and _lastY is reset
235 */
236 public boolean createNextFrame() {
237 try {
238 Frame newFrame = FrameIO.CreateFrame(_current.getFramesetName(), _current.getTitle(), null);
239
240 this.framesCreated.add(newFrame);
241
242 // add link to previous frame
243 // _prev =
244 addPreviousButton(newFrame, _current.getName());
245
246 // add link to new frame
247 // _next =
248 addNextButton(_current, newFrame.getName());
249
250 // add link to new frame
251 addFirstButton(newFrame, _firstFrame.getName());
252
253 if (encryptionLabel != null && encryptionLabel.length() > 0) {
254 newFrame.setFrameEncryptionLabel(encryptionLabel);
255 }
256
257 FrameIO.SaveFrame(_current, false);
258
259 resetGlobals(newFrame);
260 _maxX = 0;
261 return true;
262 } catch (Exception e) {
263 return false;
264 }
265 }
266
267 public List<Frame> getFramesCreated() {
268 return this.framesCreated;
269 }
270
271 private void resetGlobals(Frame toUse) {
272 Text title = toUse.getTitleItem();
273 START_X = INDENT_FROM_TITLE + title.getX();
274 START_Y = getYStart(title);
275 _lastY = START_Y;
276 _lastX = START_X;
277 // Check for @Start
278 for (Item it : toUse.getSortedItems()) {
279 if (it instanceof Text) {
280 Text t = (Text) it;
281 if (t.getText().toLowerCase().equals("@start") || t.getText().toLowerCase().startsWith("@start:")) {
282 t.stripFirstWord();
283
284 if (t.getText().equals("")) {
285 _lastY = t.getY();
286 _lastX = t.getX();
287 t.delete();
288 break;
289 }
290 }
291 }
292 }
293 _current = toUse;
294 }
295
296 public boolean addItem(Item toAdd, boolean bSave) {
297 try {
298 // if we have reached the end of the Y axis, try moving over on the
299 // X axis
300 if (_lastY >= _Mprev.getY() - _Mprev.getBoundsHeight()) {
301 _lastX = _maxX + 10;
302 _lastY = START_Y;
303
304 // if there is no more room on the X axis, we have to start a
305 // new frame
306 if (!_multiColumn || toAdd.getBoundsWidth() + _lastX > DisplayController.getFramePaintAreaWidth()) {
307 // Make sure text items that are created on the current
308 // frame are removed
309 _current.removeItem(toAdd);
310 createNextFrame();
311 }
312 }
313
314 toAdd.setPosition(_lastX, _lastY + toAdd.getBoundsHeight() / 2);
315 toAdd.setOffset(0, 0);
316 toAdd.setID(_current.getNextItemID());
317 toAdd.setRightMargin(DisplayController.getFramePaintAreaWidth(), true);
318
319 _current.addItem(toAdd);
320
321 _lastY = toAdd.getY() + toAdd.getBoundsHeight() / 2;
322 _maxX = Math.max(toAdd.getX() + toAdd.getBoundsWidth(), _maxX);
323
324 if (bSave)
325 save();
326
327 return true;
328 } catch (Exception e) {
329 return false;
330 }
331 }
332
333 public Text addText(String toAdd, Colour c, String link, String action, boolean bSave) {
334 Text text = _current.createNewText(toAdd);
335 if (c != null)
336 text.setColor(c);
337 text.setLink(link);
338 text.setAction(action);
339
340 addItem(text, bSave);
341
342 return text;
343 }
344
345 public void save() {
346 FrameIO.ForceSaveFrame(_current);
347 }
348
349 public int getLastY() {
350 return _lastY;
351 }
352
353 public void setLastY(int lastY) {
354 _lastY = lastY;
355 }
356
357 public Frame getCurrentFrame() {
358 return _current;
359 }
360
361 /**
362 * Returns the Frame name of the current frame for the FrameCreator
363 *
364 * @return The current frame for the FrameCreator
365 */
366 public String getCurrent() {
367 if (_current == null)
368 return null;
369
370 return _current.getName();
371 }
372
373 public Frame getFirstFrame() {
374 return _firstFrame;
375 }
376
377 public Item addNextButton(Frame current, String link) {
378 return addButton(_Mnext, current, link);
379 }
380
381 public Item addPreviousButton(Frame current, String link) {
382 return addButton(_Mprev, current, link);
383 }
384
385 public Item addFirstButton(Frame current, String link) {
386 return addButton(_Mfirst, current, link);
387 }
388
389 public Item addButton(Item template, Frame current, String link) {
390 // add link to new frame
391 Item previousButton = template.copy();
392 previousButton.setID(current.getNextItemID());
393 previousButton.setLink(link);
394 previousButton.setLinkHistory(false);
395 previousButton.setLinkMark(false);
396 // previousButton.setPermission(new
397 // PermissionPair(UserAppliedPermission.followLinks));
398 current.addItem(previousButton);
399
400 return previousButton;
401 }
402
403 public void addSpace(int space) {
404 _lastY += space;
405 }
406
407 public static int getYStart(Item title) {
408 return title.getY() + title.getBoundsHeight();
409 }
410
411 public void setTitle(String titleText) {
412 _current.setTitle(titleText);
413 }
414}
Note: See TracBrowser for help on using the repository browser.