1 /++ 2 Contains functions that might be useful in making new widgets, 3 like for formatting text. 4 +/ 5 module qui.utils; 6 7 import qui.qui; 8 9 import utils.misc; 10 import std.conv : to; 11 12 /// To scroll a line, by an xOffset 13 /// 14 /// Can be used to scroll to right, or to left (by making xOffset negative). 15 /// Can also be used to fill an empty line with empty space (`' '`) to make it fill width, if `line.length < width` 16 /// 17 /// Arguments: 18 /// * `line` is the full line 19 /// * `xOffset` is the number of characters scrolled right 20 /// * `width` is the number of characters that are to be displayed 21 /// 22 /// Returns: the text that should be displayed 23 dstring scrollHorizontal(dstring line, int xOffset, uint width, dchar spaceChar = ' '){ 24 dchar[] r; 25 r.length = width; 26 r[] = spaceChar; 27 for (uint i = xOffset < 0 ? -xOffset : 0; i + xOffset < line.length && i < width; i ++) 28 r[i] = line[i + xOffset]; 29 return cast(dstring)r; 30 } 31 /// 32 unittest{ 33 assert("0123456789".scrollHorizontal(5, 2) == "56"); 34 assert("0123456789".scrollHorizontal(0,10) == "0123456789"); 35 assert("0123456789".scrollHorizontal(10,4) == " "); 36 assert("0123456789".scrollHorizontal(-5,4) == " "); 37 assert("0123456789".scrollHorizontal(-5,6) == " 0"); 38 assert("0123456789".scrollHorizontal(-1,11) == " 0123456789"); 39 assert("0123456789".scrollHorizontal(-5,10) == " 01234"); 40 } 41 42 /// ditto 43 dchar[] scrollHorizontal(dchar[] line, int xOffset, uint width){ 44 return cast(dchar[])(cast(dstring)line).scrollHorizontal(xOffset, width); 45 } 46 /// ditto 47 char[] scrollHorizontal(char[] line, int xOffset, uint width){ 48 return cast(char[])(cast(dstring)line).scrollHorizontal(xOffset, width); 49 } 50 51 /// Adjusts offset (aka _scrollX or _scrollY) in scrolling so the selected character is visible TODO: FIX THIS 52 /// 53 /// Arguemnts: 54 /// * `selected` is the character on which the cursor is. If it's >lineWidth, `selected=lineWidth` 55 /// * `size` is the width/height (depending on if it's horizontal or vertical scrolling) of the space where the line is to be displayed 56 /// * `offset` is the variable storing the offset (_xOffset or _yOffset) 57 void adjustScrollingOffset(ref uint selected, uint size, uint lineWidth, ref uint offset){ 58 // if selected is outside size, it shouldn't be 59 if (selected > lineWidth) 60 selected = lineWidth; 61 // range of characters' index that's visible (1 is inclusive, 2 is not) 62 uint visible1, visible2; 63 visible1 = offset; 64 visible2 = offset + size; 65 if (selected < visible1 || selected >= visible2){ 66 if (selected < visible1){ 67 // scroll back 68 offset = selected; 69 }else if (selected >= visible2){ 70 // scroll ahead 71 offset = selected+1 - size; 72 } 73 } 74 } 75 76 /// Center-aligns text 77 /// 78 /// If `text.length > width`, the exceeding characters are removed 79 /// 80 /// Returns: the text center aligned in a string 81 dstring centerAlignText(dstring text, uint width, dchar fill = ' '){ 82 dchar[] r; 83 r.length = width; 84 if (text.length < width){ 85 uint offset = (width - cast(uint)text.length)/2; 86 r[0 .. offset] = fill; 87 r[offset .. offset+text.length][] = text; 88 r[offset+text.length .. r.length] = fill; 89 }else 90 r[] = text[0 .. r.length]; 91 return cast(dstring)r; 92 } 93 /// 94 unittest{ 95 assert("qwr".centerAlignText(7) == " qwr "); 96 assert("qwerty".centerAlignText(6) == "qwerty"); 97 assert("qwerty".centerAlignText(5) == "qwert"); 98 } 99 100 /// Returns: size after considering minimum and maximum allowed 101 /// 102 /// if `min==0`, it is ignored. if `max==0`, it is ignored 103 uint getLimitedSize(uint calculated, uint min, uint max){ 104 if (min && calculated < min) 105 return min; 106 if (max && calculated > max) 107 return max; 108 return calculated; 109 }