Changeset 200
- Timestamp:
- 07/24/10 23:59:28 (2 years ago)
- Files:
-
- trunk/src/yage/gui/surface.d (modified) (1 diff)
- trunk/src/yage/gui/textblock.d (modified) (13 diffs)
- trunk/src/yage/system/input.d (modified) (4 diffs)
Legend:
- Unmodified
- Added
- Removed
- Modified
- Copied
- Moved
trunk/src/yage/gui/surface.d
r198 r200 383 383 //textBlock.update(text, cs, width, height); 384 384 textBlock.update(textBlock.getHtml(), cs, width, height); 385 Image textImage = textBlock.render( cs,true, editable && focusSurface is this ? &textCursor : null); // TODO: Change true to Probe.NextPow2385 Image textImage = textBlock.render(true, editable && focusSurface is this ? &textCursor : null); // TODO: Change true to Probe.NextPow2 386 386 387 387 if (textImage) trunk/src/yage/gui/textblock.d
r198 r200 55 55 private char[] html; 56 56 package InlineStyle style; // base style of entire text block 57 private Style.TextAlign alignment; 57 58 private int width; 58 59 private int height; … … 61 62 private ArrayBuilder!(Letter) letters; 62 63 private ArrayBuilder!(InlineStyle) styles; // Styles pointed to by the letters 63 64 65 64 66 65 /// Functions for converting between line/letter/cursor space and x/y position. 67 66 struct { 68 67 69 /// 68 /** 69 * Get the xy pixel position of a cursor position. */ 70 70 Vec2i cursorToXy(int position) 71 71 { 72 // Special case 72 73 if (!lines.length) 73 return Vec2i(0); 74 return Vec2i(Line.getOffset(0, width, alignment), 0); 75 76 // Get y value 74 77 Vec2i result; 75 int line = cursorToLine(position); 76 //Log.trace(line, " ", position); 78 int line = cursorToLine(position); // modifies position 77 79 for (int i=0; i<line; i++) 78 80 result.y += lines[i].height; 79 line = min(line, lines.length-1); 81 82 // Get x value 80 83 int last = min(lines[line].letters.length, position); 81 84 for (int i=0; i<last; i++) 82 85 result.x += lines[line].letters[i].advanceX; 86 result.x += Line.getOffset(lines[line].width, width, alignment); 83 87 return result; 84 88 } 85 89 90 /** 91 * Get the cursor position from an xy pixel position. */ 86 92 int xyToCursor(Vec2i xy) 87 93 { 94 // Calculate line 88 95 int line; 89 for (; line<lines.length && 0 <= xy.y; line++) 90 xy.y -= lines[line].height; 91 96 for (; line<lines.length-1 && 0 <= xy.y; line++) 97 xy.y -= lines[line].height; 98 99 // Take alignment into account 100 int lineWidth = lines.length ? lines[line].width : 0; 101 xy.x -= Line.getOffset(lineWidth, width, alignment); 102 103 // Calculate position on line. 92 104 int position; 93 105 for (; position<lines[line].letters.length && 0 < xy.x; position++) … … 99 111 100 112 /** 101 * Get a line number and the position in that line from a position relative to the start of the TextBlock113 * Convert an absolute cursor position to a line/position pair. 102 114 * Params: 103 115 * position = Character position from the beginning of the TextBlock 104 116 * After the function executes, this will be the position on the line returned. 105 * Returns: The line number. If position is after the last line, then the number of the last line is returned.*/ 117 * Returns: The line number. If position is after the last line, 118 * then the number of the last line is returned and position is an offset from this.*/ 106 119 int cursorToLine(inout int position) 107 { foreach (i, line; lines.data) 108 { if (position <= line.letters.length) 120 { if (!lines.length) // special case if no lines 121 return position = 0; 122 123 foreach (i, line; lines.data) 124 { if (position < line.letters.length) 109 125 return i; 110 126 position -= line.letters.length; 111 127 } 128 position += lines.data[$-1].letters.length; 112 129 return lines.length-1; 113 130 } 114 131 115 132 /** 116 * Get cursor position from the beginning of the TextBlock based on a line number and the position in that line.133 * Convert a cursor line/position pair to an absolute position. 117 134 * Params: 118 135 * line = 119 * position = Position from the beginning of the line .120 * Returns: */136 * position = Position from the beginning of the line, may be negative or exceed the line length. 137 * Returns: The absolute position of the cursor from the beginning of the text block. */ 121 138 int lineToCursor(int line, int position) 122 139 { int m = min(line, lines.length); … … 127 144 } 128 145 146 /// 129 147 char[] getHtml() 130 148 { return html; … … 137 155 * mod = modifier key. 138 156 * unicode = Unicode value of the pressed key. 139 * cursor = The Surface's TextCursor. 140 */ 157 * cursor = The Surface's TextCursor. */ 141 158 void input(int key, int mod, dchar unicode, inout TextCursor cursor, Style computedStyle) 142 159 { … … 144 161 //Log.trace(cursor.position, " " , letters.length); 145 162 assert(cursor.position <= letters.length); 163 static int xPosition; // save the cursor's x position when moving from one line to the next. 146 164 147 165 // Position cursor 148 int position = cursor.position; 149 int currentLine = cursorToLine(position); 166 int linePosition = cursor.position; 167 int currentLine = cursorToLine(linePosition); 168 if (key != SDLK_UP && key != SDLK_DOWN) 169 xPosition = 0; // clear stored x cursor position 150 170 switch(key) 151 171 { 152 172 // Positioning keys 153 case SDLK_LEFT: if (cursor.position>0) cursor.position--; break; 154 case SDLK_RIGHT: if (cursor.position<letters.length) cursor.position++; break; 173 case SDLK_LEFT: 174 if (cursor.position>0) 175 cursor.position--; 176 break; 177 case SDLK_RIGHT: 178 if (cursor.position<letters.length) 179 cursor.position++; 180 break; 155 181 case SDLK_UP: 156 if (currentLine > 0) 157 { Vec2i xy = cursorToXy(cursor.position).x; 158 xy.y -= lines[currentLine].height; 159 cursor.position = lineToCursor(currentLine, xyToCursor(xy)); 182 if (currentLine > 0) // [below] get the x position on the current line 183 { Line* newLine = lines[currentLine-1]; 184 int i; 185 int x = xPosition = xPosition ? xPosition : cursorToXy(cursor.position).x; 186 x -= Line.getOffset(newLine.width, width, alignment); 187 for (; i<newLine.letters.length && x >=0; i++) 188 x-= newLine.letters[i].advanceX; // find the cursor position for the previous x position 189 cursor.position = lineToCursor(currentLine-1, i-1); 160 190 } 161 191 break; 162 192 case SDLK_DOWN: 163 if (currentLine < lines.length-1) 164 { Vec2i xy = cursorToXy(cursor.position).x; 165 xy.y += lines[currentLine].height; 166 cursor.position = lineToCursor(currentLine, xyToCursor(xy)); 193 if (currentLine < (cast(int)lines.length)-1) 194 { Line* newLine = lines[currentLine+1]; 195 int i; 196 int x = xPosition = xPosition ? xPosition : cursorToXy(cursor.position).x; 197 x -= Line.getOffset(newLine.width, width, alignment); 198 for (; i<newLine.letters.length && x >=0; i++) 199 x-= newLine.letters[i].advanceX; 200 cursor.position = lineToCursor(currentLine+1, i-1); 167 201 } 168 202 break; 169 203 case SDLK_HOME: 170 cursor.position -= position;204 cursor.position -= linePosition; 171 205 break; 172 206 case SDLK_END: 173 cursor.position += (lines[currentLine].letters.length - position); 207 auto letters = lines[currentLine].letters; 208 int newPosition = (cast(int)letters.length) - linePosition; 209 if (currentLine != lines.length-1) 210 newPosition--; // if not the last line, go back one before the character that causes the new line. 211 cursor.position += newPosition; 174 212 break; 175 213 … … 211 249 212 250 213 // TODO: click to position cursor, selection, ctrl+a, z, x, c, v251 // TODO: tabs, center cursor position, end crashes on centered textblock, click to position cursor, selection, ctrl+a, z, x, c, v 214 252 } 215 253 … … 231 269 * Returns: An RGBA image of width pixels wide and is shorter or equal to height. 232 270 * Note that the same buffer is used for each return, so one call to this function will overwrite a previous result.*/ 233 Image render( Style style,bool pow2=false, TextCursor* cursor=null)271 Image render(bool pow2=false, TextCursor* cursor=null) 234 272 { 235 273 Image result; … … 254 292 foreach (i, line; lines.data) 255 293 { 256 if (style.textAlign == Style.TextAlign.RIGHT) 257 x = width - line.width; 258 else if (style.textAlign == Style.TextAlign.CENTER) 259 x = (width - line.width) / 2; 294 x = Line.getOffset(line.width, width, alignment); 260 295 261 296 foreach (letter; line.letters) … … 303 338 if (cursor) 304 339 { Vec2i xy = cursorToXy(cursor.position); 305 int lineHeight = cast(int)style.lineHeight .toPx(0);340 int lineHeight = cast(int)style.lineHeight; 306 341 if (letters.length) 307 { //xy.x += letters[cursor.position].advanceX; 308 int position = cursor.position; // copy 342 { int position = cursor.position; // copy to prevent inout modification 309 343 int line = min(cursorToLine(position), lines.length-1); 310 344 lineHeight = lines[line].height; 311 345 } 346 312 347 int hmin = max(0, xy.y), hmax = min(lineHeight+xy.y, height); 313 int wmin = max(0, xy.x), wmax = min(xy.x+ 2, width);348 int wmin = max(0, xy.x), wmax = min(xy.x+1, width); 314 349 for (int h=hmin; h<hmax; h++) 315 350 for (int w=wmin; w<wmax; w++) … … 389 424 { 390 425 InlineStyle istyle = InlineStyle(style); 426 alignment = style.textAlign; 391 427 392 428 // If text has changed … … 524 560 Style.TextDecoration textDecoration; 525 561 float lineHeight; 526 float letterSpacing; 562 float letterSpacing; // not supported yet 527 563 528 564 /* … … 572 608 { Line result; 573 609 return result; 610 } 611 612 static int getOffset(int lineWidth, int width, Style.TextAlign align_) 613 { if (align_ == Style.TextAlign.LEFT) 614 return 0; 615 if (align_ == Style.TextAlign.CENTER) 616 return (width - lineWidth) / 2; 617 return width - lineWidth; // TextAlign.RIGHT 574 618 } 575 619 } trunk/src/yage/system/input.d
r198 r200 55 55 lastKeyDown = event.key.keysym; 56 56 lastKeyDownTime = clock()*1000 / CLOCKS_PER_SEC; 57 } 57 } 58 58 break; 59 59 case SDL_KEYUP: 60 60 if(focus) 61 61 focus.keyUp(event.key.keysym.sym, event.key.keysym.mod); 62 lastKeyDownTime = uint.max; 62 if (event.key.keysym.sym==lastKeyDown.sym) // if the same key we're repeating 63 lastKeyDownTime = uint.max; // stop repeating 63 64 break; 64 65 … … 84 85 currentSurface.mouseMove(event.button.button, Vec2i(event.motion.xrel, event.motion.yrel)); 85 86 86 // if the surface that the mouse is in has changed87 // If the surface that the mouse is in has changed 87 88 auto over = getMouseSurface(surface); 88 89 if(currentSurface !is over) … … 90 91 if(currentSurface) //Tell it that the mouse left 91 92 currentSurface.mouseOut(over, event.button.button, mouse); 92 if(over) //Tell it that the mo sue entered93 if(over) //Tell it that the mouse entered 93 94 over.mouseOver(event.button.button, mouse); 94 95 … … 116 117 if (focus) 117 118 { 118 uint now = clock()*1000/CLOCKS_PER_SEC; 119 uint now = clock()*1000/CLOCKS_PER_SEC; // time in milliseconds 119 120 if (now - KEY_DELAY > lastKeyDownTime) 120 121 { focus.keyPress(lastKeyDown.sym, lastKeyDown.mod, lastKeyDown.unicode);
