Ticket #2438: 2438.patch
File 2438.patch, 12.9 KB (added by diana, 15 years ago) |
---|
-
modules/org.sophie2.base.model.text/src/main/java/org/sophie2/base/model/text/mvc/TextModelLogic.java
### Eclipse Workspace Patch 1.0 #P sophie
256 256 } 257 257 258 258 inputString += String.valueOf(keyChar); 259 ImmText txtToReplaceWith = new ImmHotText(inputString, textModel.inputStyle().get()); 259 HotStyleDef styles = textModel.inputStyle().get(); 260 ImmText txtToReplaceWith = new ImmHotText(inputString, styles); 260 261 SelectionInfo caretInfo = textModel.getSelectionInfo(); 261 262 TextChange change = new TextReplaceChange(new 262 263 ImmTextInterval(caretInfo.getCaret(), caretInfo.getMarkIndex()), txtToReplaceWith); 263 264 264 265 boolean result = fireChangeText(event, change, false, Place.RIGHT); 265 266 267 if (result) { 268 textModel.inputStyle().set(HotStyleDef.getEmpty()); 269 } 266 270 return result; 267 271 } 268 272 }, … … 404 408 int caretPos = caretInfo.getCaret(); 405 409 int markPos = caretInfo.getMarkIndex(); 406 410 411 Map<HotAttr<?>, Object> styleValues = new HashMap<HotAttr<?>, Object>(); 412 styleValues.put(attr, attrValue); 413 HotStyleDef newStyles = textModel.inputStyle().get().derive(styleValues); 407 414 if (caretPos - markPos == 0) { 408 Map<HotAttr<?>, Object> styleValues = new HashMap<HotAttr<?>, Object>(); 409 styleValues.put(attr, attrValue); 410 textModel.inputStyle().set(textModel.inputStyle().get().derive(styleValues)); 415 textModel.inputStyle().set(newStyles); 411 416 return true; 412 417 } 413 418 414 419 ImmTextInterval selection = new ImmTextInterval(markPos, 415 420 caretPos); 416 Map<HotAttr<?>, Object> styleValues = new HashMap<HotAttr<?>, Object>(); 417 styleValues.put(attr, attrValue); 418 HotStyleDef style = HotStyleDef.getEmpty().derive(styleValues); 419 TextChange change = new TextStyleChange(selection, style); 421 // HotStyleDef style = HotStyleDef.getEmpty().derive(styleValues); 422 TextChange change = new TextStyleChange(selection, newStyles); 420 423 421 424 boolean handled = LogicR3.fire( 422 425 createChangeText(change, Message.create(APPLY_STYLE), event, true)); … … 507 510 HotAttr<?> attr = event.getEventParam( 508 511 TextView.EventIds.ATTR_PARAM_INDEX, HotAttr.class); 509 512 assert attr.getValueClass().equals(Boolean.class); 510 if (selection.getBegin() - selection.getEnd() == 0) { 513 boolean emptySelection = selection.isEmpty(); 514 if (emptySelection) { 511 515 512 516 if (selection.getBegin() - text.getBegin() > 0) { 513 517 … … 520 524 || text.getStyleValue(attr, selection) == null ? 521 525 (Boolean)attr.getDefaultValue() : (Boolean)text.getStyleValue(attr, selection); 522 526 Object attrValue = !oldValue && !(Boolean) textModel.inputStyle().get().getValue(attr); 527 523 528 // Trim the params. 524 529 List<Object> fields = new ArrayList<Object>( 525 530 event.getFields().subList(EventR3.SOURCE_INDEX, EventR3.PARAMS_INDEX)); -
modules/org.sophie2.dev/src/test/java/org/sophie2/dev/author/TestCtrlBText.java
1 package org.sophie2.dev.author; 2 3 import java.util.Arrays; 4 import java.util.EnumSet; 5 import java.util.List; 6 7 import javax.swing.SwingUtilities; 8 9 import org.junit.Before; 10 import org.junit.Test; 11 import org.sophie2.base.model.resources.r4.ResourceRefR4; 12 import org.sophie2.base.model.resources.r4.changes.AutoAction; 13 import org.sophie2.base.model.text.BaseModelTextModule; 14 import org.sophie2.base.model.text.elements.CommonAttr; 15 import org.sophie2.base.model.text.model.ImmHotText; 16 import org.sophie2.base.model.text.model.ImmText; 17 import org.sophie2.base.model.text.model.ImmTextInterval; 18 import org.sophie2.base.model.text.mvc.TextView.EventIds; 19 import org.sophie2.base.skins.Message; 20 import org.sophie2.base.visual.interaction.InputEventR3; 21 import org.sophie2.base.visual.interaction.InputModifier; 22 import org.sophie2.base.visual.interaction.ModifierSet; 23 import org.sophie2.core.modularity.SophieModule; 24 import org.sophie2.core.mvc.LogicR3; 25 import org.sophie2.core.mvc.events.EventR3; 26 import org.sophie2.core.testing.SystemTest; 27 import org.sophie2.dev.testing.SystemTestBase; 28 import org.sophie2.main.app.halos.MainAppHalosModule; 29 import org.sophie2.main.app.layout.MainAppLayoutModule; 30 import org.sophie2.main.app.menus.MainAppMenusModule; 31 import org.sophie2.main.app.model.MainAppModelModule; 32 import org.sophie2.main.func.resources.MainFuncResourcesModule; 33 import org.sophie2.main.func.text.InsertTextItem; 34 import org.sophie2.main.func.text.TextFuncModule; 35 import org.sophie2.main.func.text.model.HeadTextFrameH; 36 import org.sophie2.main.func.text.view.HeadTextFrameView; 37 import org.sophie2.main.func.text.view.SceneTextView; 38 import org.sophie2.main.func.text.view.TextFrameView; 39 40 /** 41 * @author Diana 42 * 43 */ 44 @SystemTest 45 public class TestCtrlBText extends SystemTestBase { 46 /** 47 * Constant created for insertion of a full text frame. 48 * Constant created to be a parameter of a message of an {@link AutoAction}. 49 * Used for skinning. Used in the test. 50 */ 51 public static final String INSERT_FULL_TEXT_FRAME = "Insert a full text frame"; 52 53 @SuppressWarnings("unchecked") 54 @Override 55 protected List<Class<? extends SophieModule>> fillDependencies() { 56 57 List<Class<? extends SophieModule>> res = super.fillDependencies(); 58 List<Class<? extends SophieModule>> toAppend = 59 Arrays.asList( 60 MainAppMenusModule.class, 61 BaseModelTextModule.class, 62 MainAppHalosModule.class, 63 TextFuncModule.class, 64 MainAppLayoutModule.class, 65 MainAppModelModule.class, 66 MainFuncResourcesModule.class 67 ); 68 69 merge(res, toAppend); 70 71 return res; 72 } 73 74 @Override 75 @Before 76 protected void setUp() throws Exception { 77 super.setUp(); 78 SwingUtilities.invokeAndWait(new Runnable() { 79 80 @SuppressWarnings("synthetic-access") 81 public void run() { 82 createNewBook(); 83 } 84 }); 85 86 try { 87 Thread.sleep(10000); 88 } catch (InterruptedException e) { 89 //nothing 90 } 91 final ImmText text = new ImmHotText( 92 "asd", null); 93 94 SwingUtilities.invokeAndWait(new Runnable() { 95 96 @SuppressWarnings("synthetic-access") 97 public void run() { 98 HeadTextFrameH.createTextFrameAction(curBook(), 99 curPageWorkArea().getRootPageView().model().get(), 100 text, ResourceRefR4.NONE_REF.toUri(), null, 101 Message.create(INSERT_FULL_TEXT_FRAME), true, false); 102 103 TextFrameView frameViewToSelect = 104 curPageWorkArea().getAll(TextFrameView.class).get(0); 105 curPageWorkArea().getSel().select(frameViewToSelect, false); 106 107 final HeadTextFrameView selectedFrameView = 108 curPageWorkArea().getSel().getSingleSelected(HeadTextFrameView.class); 109 assertNotNull(selectedFrameView); 110 111 } 112 }); 113 114 115 } 116 117 118 119 /** 120 * Tests the insert/delete in chain. 121 * 122 * @throws Exception 123 * Upon error 124 */ 125 @Test 126 public void testCtrlB() throws Exception { 127 128 HeadTextFrameView selectedFrameView = 129 curPageWorkArea().getSel().getSingleSelected(HeadTextFrameView.class); 130 131 selectedFrameView.textFlow().get().setSelectionInfo(3, 3); 132 133 SceneTextView selView = selectedFrameView.textView().get(); 134 LogicR3.fire(new EventR3(selView, null, null, null, EventIds.SWITCH_STYLE, 135 CommonAttr.BOLD)); 136 assertTrue(selectedFrameView.textFlow().get().inputStyle().get().getValue(CommonAttr.BOLD)); 137 LogicR3.fire(new EventR3(selView, 138 null, null, null, InputEventR3.KEY_TYPED, 139 new ModifierSet(EnumSet.noneOf(InputModifier.class)), 'A')); 140 141 assertTrue(selectedFrameView.textFlow().get().getRawText().getStyleValue(CommonAttr.BOLD, 142 new ImmTextInterval(3,4))); 143 LogicR3.fire(new EventR3(selView, null, null, null, EventIds.SWITCH_STYLE, 144 CommonAttr.BOLD)); 145 146 assertFalse(selectedFrameView.textFlow().get().inputStyle().get().getValue(CommonAttr.BOLD)); 147 LogicR3.fire(new EventR3(selView, 148 null, null, null, InputEventR3.KEY_TYPED, 149 new ModifierSet(EnumSet.noneOf(InputModifier.class)), 'B')); 150 assertFalse(selectedFrameView.textFlow().get().getRawText().getStyleValue(CommonAttr.BOLD, 151 new ImmTextInterval(4,5))); 152 153 } 154 155 /** 156 * Tests when pressing ctrl+b on empty text frame. 157 */ 158 @Test 159 public void testCtrlBException() { 160 InsertTextItem textItem = findMenu(InsertTextItem.class); 161 textItem.clicked(); 162 163 TextFrameView frameViewToSelect = 164 curPageWorkArea().getAll(TextFrameView.class).get(1); 165 curPageWorkArea().getSel().select(frameViewToSelect, false); 166 HeadTextFrameView selectedFrameView = 167 curPageWorkArea().getSel().getSingleSelected(HeadTextFrameView.class); 168 SceneTextView selView = selectedFrameView.textView().get(); 169 try { 170 ModifierSet mSet = new ModifierSet(InputModifier.M_CONTROL); 171 LogicR3.fire(new EventR3(selView, 172 null, null, null, InputEventR3.KEY_TYPED, 173 mSet, 'b')); 174 } catch (Exception e) { 175 fail(); 176 } 177 } 178 179 } -
modules/org.sophie2.base.model.text/src/main/java/org/sophie2/base/model/text/model/ImmHotText.java
107 107 newStyles = unitAt(styleIndex).getStyle(); 108 108 } 109 109 if (! interval.isEmpty() && interval.getBegin() != getEnd()) { 110 newStyles = newStyles. replaceDerive(this.unitAt(interval.getBegin()).getStyle());110 newStyles = newStyles.derive(this.unitAt(interval.getBegin()).getStyle()); 111 111 } 112 112 // XXX I do not agree we should bypass invalid intervals --kyli 113 113 for (int i = index; i < Math.min(interval.getEnd(), getEnd()); ++i) { … … 119 119 if (newText.getEnd() >= 1) { 120 120 TextUnit unit = newText.unitAt(0); 121 121 HotStyleDef style = unit.getStyle(); 122 newStyle = newStyle. replaceDerive(style);122 newStyle = newStyle.derive(style); 123 123 } 124 124 125 125 for (int i = 0; i < newText.getEnd(); ++i, ++index) { -
modules/org.sophie2.base.model.text/src/main/java/org/sophie2/base/model/text/style/HotStyleDef.java
37 37 38 38 private static final Map<ImmMap<HotAttr<?>, Object>, HotStyleDef> usedStyles = 39 39 new HashMap<ImmMap<HotAttr<?>,Object>, HotStyleDef>(); 40 41 40 41 42 42 private HotStyleDef(ImmMap<HotAttr<?>, Object> values) { 43 43 // Disable direct instantiation. 44 44 ImmMap<HotAttr<?>, Object> allValues = values; 45 45 46 46 if (allValues == null) { 47 47 allValues = ImmTreeMap.<HotAttr<?>, Object>empty(); 48 48 } … … 72 72 public ImmMap<HotAttr<?>, Object> getValues() { 73 73 return this.attrValues; 74 74 } 75 75 76 76 /** 77 77 * Retrieves a default style. 78 78 * … … 158 158 concat = concat.remove(key); 159 159 } 160 160 } 161 162 161 return internDef(concat); 163 162 } 164 163 … … 175 174 public HotStyleDef derive(HotStyleDef style) { 176 175 177 176 ImmMap<HotAttr<?>, Object> concat = this.attrValues; 178 177 179 178 Iterator<ImmMap.ImmEntry<HotAttr<?>, Object>> it = style.attrValues.iterator(); 180 179 while (it.hasNext()) { 181 180 ImmMap.ImmEntry<HotAttr<?>, Object> entry = it.next(); … … 187 186 concat = concat.remove(entry.getKey()); 188 187 } 189 188 } 190 191 189 return internDef(concat); 192 190 } 193 191 … … 206 204 207 205 ImmMap<HotAttr<?>, Object> concat = this.attrValues; //getNonDefaultKeys(this.attrValues); 208 206 Iterator<ImmMap.ImmEntry<HotAttr<?>, Object>> it = style.attrValues.iterator(); //getNonDefaultKeys(style.attrValues).iterator(); 209 207 210 208 while (it.hasNext()) { 211 209 ImmMap.ImmEntry<HotAttr<?>, Object> entry = it.next(); 212 210 HotAttr<?> key = entry.getKey(); … … 246 244 HotStyleDef otherStyle = (HotStyleDef) obj; 247 245 248 246 for (HotAttr<?> attr : allAttributes) { 247 if (! (otherStyle.attrValues.contains(attr) && this.attrValues.contains(attr) || 248 (!otherStyle.attrValues.contains(attr) && !this.attrValues.contains(attr)))) { 249 return false; 250 } 249 251 if (! otherStyle.getValue(attr).equals(this.getValue(attr))) { 250 252 return false; 251 253 } 254 252 255 } 253 256 return true; 254 257 } 255 258 256 259 257 260 @Override 258 261 public int hashCode() { 259 262 final int prime = 31;