Ticket #2171: performance.patch
File performance.patch, 40.1 KB (added by mira, 15 years ago) |
---|
-
src/test/java/org/sophie2/dev/author/PlainTextImportTest.java
### Eclipse Workspace Patch 1.0 #P org.sophie2.dev
87 87 88 88 TextFrameView frame = (TextFrameView) vw; 89 89 TextFrameH firstFrameContent = frame.model().get(); 90 HotTextResourceH text1 = firstFrameContent.getHeadHelper(vw.getBookView() ).getTextModel();90 HotTextResourceH text1 = firstFrameContent.getHeadHelper(vw.getBookView().model().get()).getTextModel(); 91 91 ImmHotText ht = text1.getText(); 92 92 93 93 BufferedReader reader = new BufferedReader(new FileReader(plainFile.getAbsolutePath())); -
src/test/java/org/sophie2/dev/author/HtmlImportTest.java
93 93 94 94 TextFrameView frame = (TextFrameView) vw; 95 95 TextFrameH firstFrameContent = frame.model().get(); 96 HotTextResourceH text1 = firstFrameContent.getHeadHelper(vw.getBookView() ).getTextModel();96 HotTextResourceH text1 = firstFrameContent.getHeadHelper(vw.getBookView().model().get()).getTextModel(); 97 97 ImmHotText ht = text1.getText(); 98 98 99 99 StyledEditorKit kit = new HTMLEditorKit(); -
src/test/java/org/sophie2/dev/author/TextChainingSystemTest.java
247 247 assertEquals(ChainingMode.AUTO_CHAINING, selectedFrameView.model().get().getChainMode()); 248 248 assertEquals(EXPECTED_PAGE_COUNT, curBook().getPageCount()); 249 249 assertEquals(EXPECTED_FRAME_COUNT, selectedFrameView.model().get().getChainedFrames( 250 selectedFrameView.getBookView() ).size());250 selectedFrameView.getBookView().model().get()).size()); 251 251 } 252 252 253 253 /** -
src/main/java/org/sophie2/base/model/text/smart/layout/HotLayout.java
#P org.sophie2.base.model.text
137 137 List<ImmArea> areas = this.layout.getAreas(); 138 138 int lastIndex = areas.size() - 1; 139 139 if (lastIndex == -1) { 140 return -1; 140 if (text.getLength() == 0) { 141 return -1; 142 } 143 return 0; 141 144 } 142 145 int firstInLastPage = areas.size() - areasCount; 143 146 ImmHotText hotText = this.getAreaContent(firstInLastPage); … … 157 160 return dryRun(text, areasToAdd, this); 158 161 } 159 162 160 /**161 * Simpler and faster check whether the layout is surely appropriate and does not need162 * any corrections. Its evaluation is based on the assumption that the last page of the163 * chain contains only one chained frame.164 *165 * @param text166 * The text that needs to be laid out.167 *168 * @return169 * True if the current layout is ok, false otherwise.170 */171 public boolean isLayoutOK(ImmHotText text) {172 ImmHotText lastAreaText = this.getAreaContent(this.layout.getAreas().size() -1);173 174 if ((lastAreaText.getLength() != 0) && this.isTextConsumed(text)){175 return true;176 }177 return false;178 }163 // /** 164 // * Simpler and faster check whether the layout is surely appropriate and does not need 165 // * any corrections. Its evaluation is based on the assumption that the last page of the 166 // * chain contains only one chained frame. 167 // * 168 // * @param text 169 // * The text that needs to be laid out. 170 // * 171 // * @return 172 // * True if the current layout is ok, false otherwise. 173 // */ 174 // public boolean isLayoutOK(ImmHotText text) { 175 // ImmHotText lastAreaText = this.getAreaContent(this.layout.getAreas().size() -1); 176 // 177 // if ((lastAreaText.getLength() != 0) && this.isTextConsumed(text)){ 178 // return true; 179 // } 180 // return false; 181 // } 179 182 180 183 private static int dryRun(ImmHotText text, List<ImmArea> areasToAdd, HotLayout prevLayout) { 181 184 -
src/main/java/org/sophie2/base/model/resources/r4/keys/Key.java
#P org.sophie2.base.model.resources.r4
29 29 * it when building keys. 30 30 */ 31 31 public static final String SEPARATOR = ":"; 32 32 33 33 /** 34 34 * Pattern used for splitting keys. 35 35 */ … … 52 52 * The default value of the new <code>Key</code>. 53 53 */ 54 54 protected Key(ImmList<String> parts, Class<T> valueClass, T defValue) { 55 this.parts = parts;55 this.parts = filterEmptyStrings(parts); 56 56 this.valueClass = valueClass; 57 57 assert (defValue != null) : "The default value of a key should not be null."; 58 58 this.defValue = defValue; 59 59 } 60 60 61 61 /** 62 62 * Key constructor that constructs a <code>Key</code> by a given string id. 63 63 * … … 85 85 public Key(Class<T> valueClass, T defValue, String... parts) { 86 86 this(NaiveImmList.create(parts), valueClass, defValue); 87 87 } 88 89 88 89 90 90 /** 91 91 * Retrieves the value class for this <code>Key</code>. 92 92 * … … 114 114 * The id of this <code>Key</code>. 115 115 */ 116 116 public String getId() { 117 if (this.parts.size() == 0) { 118 return RootKey.ROOT_ID; 119 } 117 120 if (this.parts.size() == 1) { 118 121 return this.parts.get(0); 119 122 } 120 123 121 124 StringBuilder result = new StringBuilder(); 122 125 for (String part : getParts()) { 123 if (!part.equals("")) { 124 result.append(part + Key.SEPARATOR); 125 } 126 result.append(part + Key.SEPARATOR); 126 127 } 127 128 128 129 result.deleteCharAt(result.length() - 1); 129 130 return result.toString(); 130 131 } 131 132 133 private static ImmList<String> filterEmptyStrings(ImmList<String> parts) { 134 String elem = ""; 135 ImmList<String> res = parts; 136 while (res.contains(elem)) { 137 res = res.remove(elem); 138 } 139 return res; 140 } 141 132 142 /** 133 143 * Retrieves the effective value of this <code>Key</code>. 134 144 * … … 162 172 public ImmList<String> getParts() { 163 173 return this.parts; 164 174 } 165 175 166 176 /** 167 177 * Extends the key; 168 178 * If <var>prefix</var> is for example <b>book</b>, … … 177 187 */ 178 188 protected abstract Key<T> extend(ImmList<String> prefix); 179 189 190 191 // TODO Think if it is not a good idea to make the hash code and equals methods 192 // consistent in ImmLists used for key parts. 180 193 @Override 181 194 public int hashCode() { 182 return getId() == null ? 0 : getId().hashCode(); 195 int hashCode = 0; 196 for (String part : getParts()) { 197 hashCode += part.hashCode(); 198 } 199 return hashCode; 183 200 } 184 201 185 202 @Override 186 203 public boolean equals(Object obj) { 187 204 if(obj instanceof Key<?>) { 188 String otherKeyId = ((Key<?>)obj).getId(); 189 return getId() == null ? otherKeyId == null : 190 getId().equals(otherKeyId); 205 ImmList<String> otherKeyParts = ((Key<?>)obj).getParts(); 206 if (getParts().size() != otherKeyParts.size()) { 207 if (getParts().contains("") || otherKeyParts.contains("")) { 208 System.out.println(); 209 } 210 return false; 211 } 212 for (int i = 0; i < getParts().size(); i++) { 213 if (!getParts().get(i).equals(otherKeyParts.get(i))) { 214 return false; 215 } 216 } 217 return true; 191 218 } 192 219 return false; 193 220 } 221 194 222 @Override 195 223 public String toString() { 196 224 return String.format("[%s]", RootKey.ROOT_ID_PARTS.equals(getParts()) ? "ROOT" : getId()); 197 225 } 198 226 199 227 /** 200 228 * Persist the value of some keys to and from an given {@link ValueRef}. 201 229 * -
src/main/java/org/sophie2/main/func/text/chaining/TextChainHaloButton.java
#P org.sophie2.main.func.text
4 4 import org.sophie2.base.commons.skin.IconsSet; 5 5 import org.sophie2.base.commons.util.ImageUtil; 6 6 import org.sophie2.base.halos.HudHaloButton; 7 import org.sophie2.base.model.book.BookH; 7 8 import org.sophie2.base.skins.SkinElementId; 8 9 import org.sophie2.base.visual.skins.ElementSkinPart; 9 10 import org.sophie2.base.visual.skins.RelatedChildren; 10 11 import org.sophie2.base.visual.skins.SkinPartDef; 11 12 import org.sophie2.base.visual.skins.VisualElementDef; 12 import org.sophie2.main.app.commons.book.BookView;13 13 import org.sophie2.main.app.commons.page.PageWorkArea; 14 14 import org.sophie2.main.app.halos.common.AppHaloUtil; 15 15 import org.sophie2.main.func.text.model.HeadTextFrameH; … … 50 50 return false; 51 51 } 52 52 53 Book View bookView = workArea.bookView().get();53 BookH bookH = workArea.bookView().get().model().get(); 54 54 TextFrameH selectedModel = selectedView.model().get(); 55 HeadTextFrameH headHelper = selectedModel.getHeadHelper(book View);55 HeadTextFrameH headHelper = selectedModel.getHeadHelper(bookH); 56 56 57 int chainIndex = selectedModel.getChainIndex(book View);58 int chainLength = headHelper.getChainedFrames(book View).size();57 int chainIndex = selectedModel.getChainIndex(bookH); 58 int chainLength = headHelper.getChainedFrames(bookH).size(); 59 59 60 60 return chainIndex == chainLength; 61 61 } -
src/main/java/org/sophie2/main/func/text/model/TailTextFrameH.java
3 3 import java.util.Comparator; 4 4 import java.util.List; 5 5 6 import org.sophie2.base.model.book.BookH; 6 7 import org.sophie2.base.model.resources.r4.ResourceRefR4; 7 8 import org.sophie2.base.model.resources.r4.access.ResourceAccess; 8 9 import org.sophie2.base.model.resources.r4.resources.ResourceH; 9 import org.sophie2.main. app.commons.book.BookView;10 import org.sophie2.main.func.text.view.ChainMaster; 10 11 11 12 /** 12 13 * A helper class for working with {@link TailTextFrameR4}s. … … 50 51 } 51 52 52 53 @Override 53 public HeadTextFrameH getHeadHelper(Book View bookView) {54 assert book View != null : "Cannot get the head helper in a null bookView.";54 public HeadTextFrameH getHeadHelper(BookH bookH) { 55 assert bookH != null : "Cannot get the head helper from a null book."; 55 56 56 57 ResourceAccess headAccess = 57 book View.getAccess().open(getHeadReference(bookView.getAccess().getRef()), null);58 bookH.getAccess().open(getHeadReference(bookH.getAccess().getRef()), null); 58 59 59 60 return ResourceH.getHelper(headAccess, HeadTextFrameH.class); 60 61 } 61 62 62 63 @Override 63 public int getChainIndex(Book View bookView) {64 assert book View != null : "Cannot get the chained index in a null bookView.";64 public int getChainIndex(BookH bookH) { 65 assert bookH != null : "Cannot get the chained index in a null book."; 65 66 66 HeadTextFrameH headFrame = getHeadHelper(bookView); 67 List<TailTextFrameH> chainedFrames = headFrame.getChainedFrames(bookView); 67 HeadTextFrameH headFrame = getHeadHelper(bookH); 68 List<TailTextFrameH> chainedFrames = 69 ChainMaster.getChainedFrames(bookH, headFrame.getRef()); 68 70 int res = chainedFrames.indexOf(this); 69 71 if (res == -1) { 70 72 res = chainedFrames.size(); -
src/main/java/org/sophie2/main/func/text/chaining/TextChainingLogic.java
10 10 import org.sophie2.base.commons.util.ImmMap; 11 11 import org.sophie2.base.commons.util.ImmMap.ImmEntry; 12 12 import org.sophie2.base.halos.HaloButton; 13 import org.sophie2.base.model.book.BookH; 13 14 import org.sophie2.base.model.book.interfaces.ResourceFrame; 14 15 import org.sophie2.base.model.resources.r4.ResourceRefList; 15 16 import org.sophie2.base.model.resources.r4.ResourceRefR4; … … 39 40 import org.sophie2.main.func.text.model.TextFrameH; 40 41 import org.sophie2.main.func.text.model.TextTemplateR4; 41 42 import org.sophie2.main.func.text.utils.TextChainUtils; 43 import org.sophie2.main.func.text.view.ChainMaster; 42 44 import org.sophie2.main.func.text.view.HeadTextFrameView; 43 45 import org.sophie2.main.func.text.view.TailTextFrameView; 44 46 import org.sophie2.main.func.text.view.TextFrameView; … … 70 72 BoundControl.EventIds.INPUT_PARAM_INDEX, ComboInput.class); 71 73 TextFrameView selFrameView = AppHaloUtil.getSingleSelected(source, TextFrameView.class); 72 74 BookView bookView = selFrameView.getBookView(); 73 HeadTextFrameH headH = selFrameView.model().get().getHeadHelper(bookView );75 HeadTextFrameH headH = selFrameView.model().get().getHeadHelper(bookView.model().get()); 74 76 75 77 boolean res; 76 78 ChainHudElement element = input.getSelectedItem(); … … 119 121 filter.setSourceClass(TextUnchainNextHaloButton.class); 120 122 filter.setEventId(HaloButton.EventIds.HALO_CLICK); 121 123 } 122 124 125 @SuppressWarnings("synthetic-access") 123 126 public boolean handle(EventR3 event) { 124 127 TextUnchainNextHaloButton source = event.getSource(TextUnchainNextHaloButton.class); 125 128 TextFrameView selFrameView = AppHaloUtil.getSingleSelected(source, TextFrameView.class); 126 129 127 130 assert selFrameView != null: "The halo button should be of a textFrameView"; 128 131 boolean beforeThisFrame = true; 129 splitChain (selFrameView, beforeThisFrame, false, true);132 splitChainOnly(selFrameView, beforeThisFrame, false, true); 130 133 return true; 131 134 } 132 135 … … 142 145 filter.setSourceClass(TextUnchainPrevHaloButton.class); 143 146 filter.setEventId(HaloButton.EventIds.HALO_CLICK); 144 147 } 145 148 @SuppressWarnings("synthetic-access") 146 149 public boolean handle(EventR3 event) { 147 150 TextUnchainPrevHaloButton source = event.getSource(TextUnchainPrevHaloButton.class); 148 151 TailTextFrameView selFrameView = 149 152 AppHaloUtil.getSingleSelected(source, TailTextFrameView.class); 150 153 assert selFrameView != null; 151 154 boolean beforeThisFrame = false; 152 splitChain(selFrameView, beforeThisFrame, false, true); 155 156 splitChainOnly(selFrameView, beforeThisFrame, false, true); 153 157 return true; 154 158 } 155 159 … … 169 173 170 174 } 171 175 176 @SuppressWarnings("synthetic-access") 172 177 public boolean handle(EventR3 event) { 173 178 HeadTextFrameView selFrameView = event.getEventParam(BookView.EventIds.VIEW_PARAM_INDEX, 174 179 HeadTextFrameView.class); 175 180 if (selFrameView != null) { 176 splitChain (selFrameView, true, true, false);181 splitChainOnly(selFrameView, true, true, false); 177 182 } 178 183 return false; 179 184 } 180 185 181 186 }, 182 187 183 184 188 /** 185 189 * Handles a user request to delete a page. First checks whether there are 186 190 * any head text frames on the page and unchains them. This should be … … 200 204 201 205 List<TextFrameView> textViews = pageToRemView.getAll(TextFrameView.class); 202 206 BookView bookView = pageToRemView.getBookView(); 207 BookH bookH = bookView.model().get(); 203 208 Map<ResourceRefR4, TextFrameView> toUnchain = new HashMap<ResourceRefR4, TextFrameView>(); 204 209 210 205 211 for (TextFrameView textView:textViews) { 206 212 HeadTextFrameView headView = textView.getHeadView(); 207 213 if (textViews.contains(headView)) { 208 214 HeadTextFrameH headModel = headView.model().get(); 209 if (headModel.getChainedFrames(book View).size() > 0) {215 if (headModel.getChainedFrames(bookH).size() > 0) { 210 216 TextFrameView current = toUnchain.get(headModel.getRef()); 211 217 if (TextChainUtils.TEXT_VIEW_COMP.compare(textView, current) > 0) { 212 218 toUnchain.put(headModel.getRef(), textView); … … 214 220 } 215 221 } 216 222 } 223 ChainMaster chainMaster = ChainMaster.get(bookH); 224 chainMaster.massCnanging().set(true); 217 225 for (TextFrameView textView:toUnchain.values()) { 218 226 splitChain(textView, true, true, false); 219 227 } 228 chainMaster.massCnanging().set(false); 220 229 221 230 return false; // Should not be handled! Other logics actually delete the page. 222 231 } … … 270 279 271 280 HeadTextFrameH frameToChain = (HeadTextFrameH) textFrameH; 272 281 273 List<TailTextFrameH> chainedFrames = frameToChain.getChainedFrames(bookView );282 List<TailTextFrameH> chainedFrames = frameToChain.getChainedFrames(bookView.model().get()); 274 283 ImmMap<ResourceRefR4, String> chainedFramesMap = ImmTreeMap.empty(); 275 284 for(TailTextFrameH frameH:chainedFrames) { 276 285 chainedFramesMap = chainedFramesMap.put(frameH.getRef(), frameH.getChainOrder()); … … 308 317 ResourceAccess textAccess = bookAccess.open(oldTextRef, null); 309 318 ImmHotText secondFrameText = HotTextResourceR4.KEY_TEXT.get(textAccess); 310 319 if (!secondFrameText.equals(ImmHotText.empty())) { 311 HeadTextFrameH headHelper = prevModel.getHeadHelper(bookView );320 HeadTextFrameH headHelper = prevModel.getHeadHelper(bookView.model().get()); 312 321 final ResourceRefR4 headRef = ResourceRefR4.getRelativeRef(bookRef, headHelper.getRef()); 313 322 HotTextResourceH firstFrameTextHelper = headHelper.getTextModel(); 314 323 ImmHotText firstFrameText = firstFrameTextHelper.getText(); … … 357 366 }.register(bookAccess); 358 367 } 359 368 369 // Calls the splitChain method in way that the view properties 370 // that depend on text chains will be recomputed only once 371 static private void splitChainOnly(TextFrameView frameView, boolean beforeThisFrame, 372 final boolean useSameText, boolean isSign) { 373 BookH bookH = frameView.getBookView().model().get(); 374 ChainMaster chainMaster = ChainMaster.get(bookH); 375 chainMaster.massCnanging().set(true); 376 splitChain(frameView, beforeThisFrame, useSameText, isSign); 377 chainMaster.massCnanging().set(false); 378 } 379 360 380 /** 361 381 * Helper method used to split the chain of frames from a given frame. 362 382 * … … 380 400 TextFrameH selFrameH = frameView.model().get(); 381 401 ResourceRefList chainedFramesRefs = ResourceRefList.EMPTY; 382 402 HeadTextFrameH headHelper = frameView.getHeadView().model().get(); 383 List<TailTextFrameH> chainedFrames = headHelper.getChainedFrames(bookView); 403 List<TailTextFrameH> chainedFrames = 404 headHelper.getChainedFrames(bookView.model().get()); 384 405 int thisFrameIndex = -1; 385 406 386 407 for (int i = 0; i < chainedFrames.size(); i++) { -
src/main/java/org/sophie2/main/func/text/model/TextFrameH.java
1 1 package org.sophie2.main.func.text.model; 2 2 3 import org.sophie2.base.model.book.BookH; 3 4 import org.sophie2.base.model.book.FrameH; 4 5 import org.sophie2.base.model.resources.r4.ResourceRefR4; 5 6 import org.sophie2.base.model.resources.r4.access.ResourceAccess; 6 import org.sophie2.main.app.commons.book.BookView;7 7 8 8 /** 9 9 * A helper class for working with text frames. Provides common methods for … … 36 36 /** 37 37 * Gets the helper for the head of the chain this frame is in. 38 38 * 39 * @param bookView 40 * The parent of the view associated with this model. 39 * @param bookH 40 * The parent book of this frame. 41 * 41 42 * @return The head text frame helper. 42 43 */ 43 public abstract HeadTextFrameH getHeadHelper(Book View bookView);44 public abstract HeadTextFrameH getHeadHelper(BookH bookH); 44 45 45 46 /** 46 47 * Gets the effective index of this frame in the chain. It is not 47 48 * necessarily the index of the frame in 48 * {@link HeadTextFrameH#getChainedFrames(Book View)}.49 * {@link HeadTextFrameH#getChainedFrames(BookH)}. 49 50 * 50 * @param book View51 * The parent of the view associated with this model.51 * @param bookH 52 * The parent book of this frame. 52 53 * @return 53 54 * The index of the frame in the chain. 54 55 */ 55 public abstract int getChainIndex(Book View bookView);56 public abstract int getChainIndex(BookH bookH); 56 57 } -
src/main/java/org/sophie2/main/func/text/view/TailTextFrameView.java
124 124 @Override 125 125 public Integer getIndex() { 126 126 if (getBookView() != null) { 127 return model().get().getChainIndex(getBookView() );127 return model().get().getChainIndex(getBookView().model().get()); 128 128 } 129 129 return 1; 130 130 } -
src/main/java/org/sophie2/main/func/text/utils/TextStyleUtils.java
1 1 package org.sophie2.main.func.text.utils; 2 2 3 3 4 import org.sophie2.base.model.book.BookH; 4 5 import org.sophie2.base.model.text.HotAttr; 5 6 import org.sophie2.base.model.text.mvc.TextView; 6 7 import org.sophie2.base.model.text.mvc.TextViewFlow; … … 95 96 TextViewFlow flow = contentView.textFlow().get(); 96 97 HotPos caretPos = flow.caretPos().get(); 97 98 HotPos markPos = flow.markPos().get(); 98 ImmHotText text = contentView.model().get().getHeadHelper(contentView.getBookView()) 99 BookH book = contentView.getBookView().model().get(); 100 ImmHotText text = contentView.model().get().getHeadHelper(book) 99 101 .getTextModel().getText(); 100 102 101 103 return text.getStyleValue(attribute, new HotInterval(caretPos, markPos)); -
src/main/java/org/sophie2/main/func/text/model/HeadTextFrameH.java
1 1 package org.sophie2.main.func.text.model; 2 2 3 3 import java.net.URI; 4 import java.util.Collections;5 import java.util.LinkedList;6 4 import java.util.List; 7 5 8 6 import org.sophie2.base.commons.util.ImmList; … … 25 23 import org.sophie2.base.model.resources.r4.keys.TemplatedKey.Mode; 26 24 import org.sophie2.base.model.resources.r4.resources.ResourceH; 27 25 import org.sophie2.base.model.text.smart.ImmHotText; 28 import org.sophie2.main.app.commons.book.BookView;29 import org.sophie2.main.app.commons.page.RootPageView;30 26 import org.sophie2.main.func.text.chaining.ChainingMode; 31 import org.sophie2.main.func.text.view. TailTextFrameView;27 import org.sophie2.main.func.text.view.ChainMaster; 32 28 33 29 /** 34 30 * A helper class for working with {@link HeadTextFrameR4}s. … … 85 81 } 86 82 87 83 @Override 88 public HeadTextFrameH getHeadHelper(Book View bookView) {84 public HeadTextFrameH getHeadHelper(BookH bookH) { 89 85 return this; 90 86 } 91 87 92 88 @Override 93 public int getChainIndex(Book View bookView) {89 public int getChainIndex(BookH bookH) { 94 90 return 0; 95 91 } 96 92 … … 99 95 * These are the frames the current flow will be displayed in in the order 100 96 * they should be displayed. 101 97 * 102 * @param book View98 * @param bookH 103 99 * The book view this frame is in. 104 100 * @return 105 101 * List of the frames in their chain order. 106 102 */ 107 public List<TailTextFrameH> getChainedFrames(final BookView bookView) { 108 assert bookView != null : "Cannot get the chained frames in a null bookView."; 109 110 List<TailTextFrameH> chainedFrames = new LinkedList<TailTextFrameH>(); 111 ResourceRefR4 bookRef = bookView.model().get().getRef(); 112 113 ResourceRefR4 thisRelativeRef = ResourceRefR4.getRelativeRef( 114 bookRef, getRef()); 115 116 for (ResourceRefR4 pageRef : bookView.model().get().getPages()) { 117 RootPageView pageView = bookView.getPageView(pageRef); 118 for (TailTextFrameView tailFrameView : pageView.getAll(TailTextFrameView.class)) { 119 TailTextFrameH tailModel = tailFrameView.model().get(); 120 ResourceRefR4 tailRef = tailModel.getHeadReference(bookRef); 121 if (thisRelativeRef.equals(tailRef)) { 122 chainedFrames.add(tailModel); 123 } 124 } 125 } 126 Collections.sort(chainedFrames, TailTextFrameH.CHAIN_ORDER_COMPARARTOR); 127 return chainedFrames; 103 public List<TailTextFrameH> getChainedFrames(final BookH bookH) { 104 return ChainMaster.getChainedFrames(bookH, getRef()); 128 105 } 129 106 130 107 /** -
src/main/java/org/sophie2/main/func/text/utils/TextChainUtils.java
43 43 import org.sophie2.main.func.text.model.TailTextFrameH; 44 44 import org.sophie2.main.func.text.model.TailTextFrameR4; 45 45 import org.sophie2.main.func.text.model.TextFrameH; 46 import org.sophie2.main.func.text.view.ChainMaster; 46 47 import org.sophie2.main.func.text.view.HeadTextFrameView; 47 48 import org.sophie2.main.func.text.view.TailTextFrameView; 48 49 import org.sophie2.main.func.text.view.TextFrameView; … … 78 79 assert (bookView1 == bookView2) && (view1.getHeadView() == view2.getHeadView()) : 79 80 "You can not compare text frame views from different chains"; 80 81 81 int chainOrder1 = view1.model().get().getChainIndex(bookView1); 82 int chainOrder2 = view2.model().get().getChainIndex(bookView1); 83 if (chainOrder1 < chainOrder2) { 82 if (view1 instanceof HeadTextFrameView) { 83 if (view2 instanceof HeadTextFrameView) { 84 return 0; 85 } 84 86 return -1; 85 } else if (chainOrder1 == chainOrder2) { 86 return 0; 87 } else { 87 } 88 if (view2 instanceof HeadTextFrameView) { 88 89 return 1; 89 90 } 91 92 TailTextFrameH frame1 = (TailTextFrameH) view1.model().get(); 93 TailTextFrameH frame2 = (TailTextFrameH) view2.model().get(); 94 95 return frame1.getChainOrder().compareTo(frame2.getChainOrder()); 90 96 } 91 97 }; 92 98 … … 108 114 } 109 115 chainedFrameViews.add(headFrameView); 110 116 Collections.sort(chainedFrameViews, TEXT_VIEW_COMP); 117 111 118 return chainedFrameViews; 112 119 } 113 120 … … 120 127 * which flow will be recalculated. 121 128 */ 122 129 public static void reflowText(HeadTextFrameView headFrameView) { 123 BookView bookView = headFrameView.getBookView(); 130 BookView bookView = headFrameView.getBookView(); 131 124 132 if (bookView == null || bookView.getViewOptions().isPreviewMode()) { 125 133 //this happens if the headFrame is no longer part of this bookView 126 134 return; 127 135 } 128 136 BookH bookH = bookView.model().get(); 129 137 TextViewFlow flow = headFrameView.textFlow().get(); 130 if (flow.getTextLayout().isLayoutOK(flow.getText())) {131 return;132 }133 138 134 139 //This is done here because we need to know the last frame-view... 135 140 List<TextFrameView> chainedFrameViews = getChainedFrameViews(bookView, headFrameView); … … 141 146 return; 142 147 } 143 148 boolean changesMade = true; 149 150 ChainMaster chainMaster = ChainMaster.get(bookH); 151 chainMaster.massCnanging().set(true); 144 152 if (neededPages > 0) { 145 153 expandChain(chainedFrameViews, neededPages); 146 154 } else { 147 155 changesMade = reduceChain(chainedFrameViews); 148 156 } 157 chainMaster.massCnanging().set(false); 158 149 159 if (changesMade) { 150 160 new AutoAction("Auto-fit text flow.", true) { 151 161 @Override … … 254 264 * @return 255 265 * True if the pages were added and false otherwise. 256 266 */ 257 public static boolean expandChain(List<TextFrameView> chainedTextViews, final int neededPages) { 267 public static boolean expandChain(List<TextFrameView> chainedTextViews, final int neededPages) { 268 258 269 TextFrameView lastTextView = chainedTextViews.get(chainedTextViews.size() - 1); 259 270 RootPageView page = lastTextView.findParentElement(RootPageView.class); 260 271 … … 265 276 final ResourceRefR4 pageTemplateRef = getPageTemplate(page); 266 277 267 278 List<FrameView> frameViews = page.getAll(FrameView.class); 279 268 280 final ResourceRefList frameTemplatesList = getFrameTemplates(book, frameViews); 269 281 270 282 final ImmList<String> kindsList = getFrameKinds(frameViews); 271 283 272 284 Map<ResourceRefR4, List<TextFrameView>> chainsInThisPage = 273 285 getChainsInPage(bookRef, frameViews); 274 286 final ImmList<String> frameChainOrders = 275 287 getChainOrders(bookRef, frameViews, chainedTextViews, chainsInThisPage); 288 276 289 final ImmList<Integer> frameChainIndexes = getIndexInPage(bookRef, frameViews, chainsInThisPage); 277 290 278 291 //Generate page`s and frame`s refs and titles … … 312 325 new AutoAction("Expand auto-chain", false) { 313 326 @Override 314 327 public void performAuto() { 328 315 329 int size = frameTemplatesList.size(); 316 330 ResourceRefR4 pageRef = pages.get(lastPageIndex); 317 331 ResourceRefR4 relPageTemplRef = ResourceRefR4.getRelativeRef(pageRef, pageTemplateRef); … … 425 439 426 440 return true; 427 441 } 442 428 443 429 444 private static ResourceRefList getFramesRefs(RootPageView page) { 430 445 List<FrameView> frameViews = page.getAll(FrameView.class); … … 604 619 private static String getNextOrderInChain(TextFrameView textView) { 605 620 BookView bookView = textView.getBookView(); 606 621 TextFrameH model = textView.model().get(); 607 //XXX getChainedFrames IS SO SLOW... 608 List<TailTextFrameH> wholeChain = model.getHeadHelper(bookView).getChainedFrames(bookView); 622 BookH bookH = bookView.model().get(); 623 List<TailTextFrameH> wholeChain = 624 ChainMaster.getChainedFrames(bookH, model.getHeadReference(bookH.getRef())); 609 625 int thisFrameIndex = wholeChain.indexOf(model); 610 626 if (thisFrameIndex == wholeChain.size()-1){ 611 627 return ""; … … 691 707 } 692 708 693 709 private static boolean isEmpty(TailTextFrameView tail) { 694 Book View bookView = tail.getBookView();695 int index = tail.model().get().getChainIndex(book View);710 BookH book = tail.getBookView().model().get(); 711 int index = tail.model().get().getChainIndex(book); 696 712 TextViewFlow flow = tail.textFlow().get(); 697 713 return (flow.getTextLayout().getAreaContent(index).getLength() == 0); 698 714 } -
src/main/java/org/sophie2/main/func/text/chaining/TextUnchainNextHaloButton.java
4 4 import org.sophie2.base.commons.skin.IconsSet; 5 5 import org.sophie2.base.commons.util.ImageUtil; 6 6 import org.sophie2.base.halos.ClickHaloButton; 7 import org.sophie2.base.model.book.BookH; 7 8 import org.sophie2.base.skins.SkinElementId; 8 9 import org.sophie2.base.visual.skins.ElementSkinPart; 9 10 import org.sophie2.base.visual.skins.SkinPartDef; 10 11 import org.sophie2.base.visual.skins.VisualElementDef; 11 import org.sophie2.main.app.commons.book.BookView;12 12 import org.sophie2.main.app.commons.page.PageWorkArea; 13 13 import org.sophie2.main.app.halos.common.AppHaloUtil; 14 14 import org.sophie2.main.func.text.model.HeadTextFrameH; … … 47 47 return false; 48 48 } 49 49 50 Book View bookView = workArea.bookView().get();50 BookH bookH = workArea.bookView().get().model().get(); 51 51 TextFrameH selectedModel = selectedView.model().get(); 52 HeadTextFrameH headHelper = selectedModel.getHeadHelper(book View);52 HeadTextFrameH headHelper = selectedModel.getHeadHelper(bookH); 53 53 54 int chainIndex = selectedModel.getChainIndex(book View);55 int chainLength = headHelper.getChainedFrames(book View).size();54 int chainIndex = selectedModel.getChainIndex(bookH); 55 int chainLength = headHelper.getChainedFrames(bookH).size(); 56 56 57 57 return chainIndex < chainLength; 58 58 } -
src/main/java/org/sophie2/main/func/text/view/ChainMaster.java
1 package org.sophie2.main.func.text.view; 2 3 import java.util.ArrayList; 4 import java.util.HashMap; 5 import java.util.List; 6 import java.util.Map; 7 8 import org.sophie2.base.commons.structures.ImmTreeList; 9 import org.sophie2.base.commons.structures.ImmTreeMap; 10 import org.sophie2.base.commons.util.ImmList; 11 import org.sophie2.base.commons.util.ImmMap; 12 import org.sophie2.base.model.book.BookH; 13 import org.sophie2.base.model.book.PageH; 14 import org.sophie2.base.model.resources.r4.ResourceRefR4; 15 import org.sophie2.base.model.resources.r4.resources.ResourceH; 16 import org.sophie2.core.prolib.annot.Immutable; 17 import org.sophie2.core.prolib.impl.AutoProperty; 18 import org.sophie2.core.prolib.impl.BaseProObject; 19 import org.sophie2.core.prolib.interfaces.Prop; 20 import org.sophie2.core.prolib.interfaces.RwProp; 21 import org.sophie2.main.func.text.model.HeadTextFrameH; 22 import org.sophie2.main.func.text.model.TailTextFrameH; 23 24 /** 25 * Class that keeps lists of all chains in all books opened in the application. 26 * 27 * @author mira 28 */ 29 public class ChainMaster extends BaseProObject { 30 31 private static Map<BookH, ChainMaster> chainMasters = new HashMap<BookH, ChainMaster>(); 32 33 /** 34 * Gets the ChainMaster responsible for a given BookH. If there is no such, a new one is 35 * created and added. 36 * 37 * @param bookH 38 * The book whose ChainMaster is wanted. 39 * @return 40 * The ChainMaster of a book. 41 */ 42 public static ChainMaster get(BookH bookH) { 43 if(!chainMasters.containsKey(bookH)) { 44 chainMasters.put(bookH, new ChainMaster(bookH)); 45 } 46 return chainMasters.get(bookH); 47 } 48 49 private final BookH bookH; 50 51 private ChainMaster(BookH bookH){ 52 this.bookH = bookH; 53 } 54 55 /** 56 * Flag that indicates that the model is being mass-changed and there is no need 57 * to recompute the chain info of this book. Remember to always set this back 58 * to false after the mass-changes are done. 59 * 60 * @return 61 * The Property. 62 */ 63 public RwProp<Boolean> massCnanging() { 64 return getBean().makeValueProp("massCnanging", Boolean.class, false); 65 } 66 67 /** 68 * Property that keeps the last value of chainInfo property. It is used 69 * instead of when there are mass changes. 70 * 71 * @return 72 * The Property. 73 */ 74 public RwProp<ChainInfo> oldValue() { 75 return getBean().makeValueProp("oldValue", ChainInfo.class, ChainInfo.INITIAL); 76 } 77 78 /** 79 * Property that keeps accurate information about all chained frames in a book. 80 * 81 * @return 82 * The Property. 83 */ 84 public Prop<ChainInfo> chainInfo() { 85 class chainInfo extends AutoProperty<ChainInfo> { 86 87 @SuppressWarnings("synthetic-access") 88 @Override 89 protected ChainInfo compute() { 90 if (massCnanging().get()) { 91 return oldValue().get(); 92 } 93 94 assert (ChainMaster.this.bookH != null) : 95 "Cannot get the chained frames in a null book."; 96 97 ImmMap<ResourceRefR4, ImmList<TailTextFrameH>> chainsMap = 98 ImmTreeMap.<ResourceRefR4, ImmList<TailTextFrameH>>empty(); 99 100 for (ResourceRefR4 pageRef : ChainMaster.this.bookH.getPages()) { 101 102 PageH pageH = ResourceH.getHelper(ChainMaster.this.bookH.getAccess().open(pageRef, null), PageH.class); 103 List<TailTextFrameH> tailsInPage = pageH.getSubElements(TailTextFrameH.class); 104 for (TailTextFrameH tailFrameH : tailsInPage) { 105 ResourceRefR4 bookRef = ChainMaster.this.bookH.getRef(); 106 ResourceRefR4 relHeadRef = tailFrameH.getHeadReference(bookRef); 107 ResourceRefR4 headRef = bookRef.append(relHeadRef); 108 ImmList<TailTextFrameH> chain; 109 110 if (chainsMap.contains(headRef)) { 111 chain = chainsMap.get(headRef); 112 chainsMap = chainsMap.remove(headRef); 113 int index = findIndexFor(chain, tailFrameH); 114 chain = chain.add(index, tailFrameH); 115 } else { 116 chain = ImmTreeList.create(tailFrameH); 117 } 118 chainsMap = chainsMap.put(headRef, chain); 119 } 120 } 121 ChainInfo res = new ChainInfo(chainsMap); 122 oldValue().set(res); 123 return res; 124 } 125 126 private int findIndexFor(ImmList<TailTextFrameH> chain, 127 TailTextFrameH tailFrameH) { 128 int i; 129 for (i=0;i<chain.size();i++) { 130 if (chain.get(i).getChainOrder().compareTo(tailFrameH.getChainOrder()) > 0){ 131 break; 132 } 133 } 134 return i; 135 } 136 137 } 138 return getBean().makeProp(chainInfo.class); 139 } 140 141 /** 142 * Gets all tail-frames of a given book that are chained to the given head-frame. 143 * 144 * @param bookH 145 * The book in which to look or chained frames. 146 * @param headFrame 147 * The head of the chain we look for. 148 * @return 149 * All TailTextFrames in this chain ordered by their chain-order. 150 */ 151 public static List<TailTextFrameH> getChainedFrames(BookH bookH, ResourceRefR4 headFrame) { 152 153 ChainInfo info = get(bookH).chainInfo().get(); 154 assert info != null; 155 156 List<TailTextFrameH> res = new ArrayList<TailTextFrameH>(info.getChain(headFrame).asList()); 157 //Collections.sort(res, TailTextFrameH.CHAIN_ORDER_COMPARARTOR); 158 159 return res; 160 } 161 162 /** 163 * Immutable class used to wrap an ImmMap of <ResourceRefR4, ImmList<TailTextFrameH>> elements. 164 * It is used to keep the all chains in a book. 165 * @author mira 166 */ 167 @Immutable 168 static class ChainInfo { 169 170 /** 171 * The empty chain info. 172 */ 173 public static final ChainInfo INITIAL = new ChainInfo(ImmTreeMap.<ResourceRefR4, ImmList<TailTextFrameH>>empty()); 174 private final ImmMap<ResourceRefR4, ImmList<TailTextFrameH>> chains; 175 176 private ChainInfo(ImmMap<ResourceRefR4, ImmList<TailTextFrameH>> chains) { 177 this.chains = chains; 178 } 179 180 /** 181 * Gets the last computed chain for a given {@link HeadTextFrameH}. 182 * 183 * @param headRef 184 * {@link ResourceRefR4} pointing to the head of the desired chain. 185 * @return 186 * {@link ImmList} containing the tails of the chain, ordered by chain-order. 187 * Null if the head has no tails. 188 */ 189 public ImmList<TailTextFrameH> getChain(ResourceRefR4 headRef) { 190 191 if (!this.chains.contains(headRef)) { 192 // The head does not have tails, so the chain is empty. 193 return ImmTreeList.<TailTextFrameH>empty(); 194 } 195 196 return this.chains.get(headRef); 197 } 198 199 @Override 200 public int hashCode() { 201 final int prime = 31; 202 int result = 1; 203 result = prime * result 204 + ((this.chains == null) ? 0 : this.chains.hashCode()); 205 return result; 206 } 207 208 @Override 209 public boolean equals(Object obj) { 210 if (this == obj) { 211 return true; 212 } 213 if (obj == null) { 214 return false; 215 } 216 if (getClass() != obj.getClass()) { 217 return false; 218 } 219 ChainInfo other = (ChainInfo) obj; 220 if (this.chains == null) { 221 if (other.chains != null) { 222 return false; 223 } 224 } else if (!this.chains.equals(other.chains)) { 225 return false; 226 } 227 return true; 228 } 229 230 } 231 } 232 No newline at end of file -
src/main/java/org/sophie2/main/func/text/view/HeadTextFrameView.java
98 98 99 99 @Override 100 100 public Integer getIndex() { 101 return model().get().getChainIndex(getBookView()); 101 return 0; 102 // TODO HEAD is always first... 103 // return model().get().getChainIndex(getBookView().model().get()); 102 104 } 103 105 104 106 @Override … … 164 166 if (bookView == null) { 165 167 return ImmTreeList.empty(); 166 168 } 167 return ImmTreeList.create(model().get().getChainedFrames(bookView)); 169 return ImmTreeList.create( 170 model().get().getChainedFrames(bookView.model().get())); 168 171 } 169 172 } 170 173 return getBean().makeProp(chainedFrames.class); -
src/main/java/org/sophie2/main/func/text/chaining/TextChainHud.java
82 82 textFrames.addAll(availableTextFrames); 83 83 BookView bookView = selectedView.getBookView(); 84 84 TextFrameH frameH = selectedView.model().get(); 85 HeadTextFrameH headH = frameH.getHeadHelper(bookView );85 HeadTextFrameH headH = frameH.getHeadHelper(bookView.model().get()); 86 86 if (ChainingMode.AUTO_CHAINING == headH.getChainMode()) { 87 87 selectedElem = ChainHudElement.AUTO_CHAIN_ELEM; 88 88 }