mirror of https://github.com/adamdruppe/arsd.git
catchup changes
This commit is contained in:
parent
d7c19998c5
commit
5f7dcb8e44
|
@ -8,12 +8,69 @@
|
|||
|
||||
---
|
||||
import arsd.minigui_xml;
|
||||
Window window = createWindow(`
|
||||
Window window = createWindowFromXml(`
|
||||
<MainWindow>
|
||||
<Button label="Hi!" />
|
||||
</MainWindow>
|
||||
`);
|
||||
---
|
||||
|
||||
|
||||
To add custom widgets to the minigui_xml factory, you need
|
||||
to register them with FIXME.
|
||||
|
||||
You can attach some events right in the XML using attributes.
|
||||
The attribute names are `onEVENTNAME` or `ondirectEVENTNAME`
|
||||
and the values are one of the following three value types:
|
||||
|
||||
$(LIST
|
||||
* If it starts with `&`, it is a delegate you need
|
||||
to register using the FIXME function.
|
||||
|
||||
* If it starts with `(`, it is a string passed to
|
||||
the [arsd.dom.querySelector] function to get an
|
||||
element reference
|
||||
|
||||
* Otherwise, it tries to call a script function (if
|
||||
scripting is available).
|
||||
)
|
||||
|
||||
Keep in mind
|
||||
For example, to make a page widget that changes based on a
|
||||
drop down selection, you may:
|
||||
|
||||
```xml
|
||||
<DropDownSelection onchange="$(+PageWidget).setCurrentTab">
|
||||
<option>Foo</option>
|
||||
<option>Bar</option>
|
||||
</DropDownSelection>
|
||||
<PageWidget name="mypage">
|
||||
<!-- contents elided -->
|
||||
</PageWidget>
|
||||
```
|
||||
|
||||
That will create a select widget that when it changes, it will
|
||||
look for the next PageWidget sibling (that's the meaning of `+PageWidget`,
|
||||
see css selector syntax for more) and call its `setCurrentTab`
|
||||
method.
|
||||
|
||||
Since the function knows `setCurrentTab` takes an integer, it will
|
||||
automatically pull the `intValue` member out of the event and pass
|
||||
it to the method.
|
||||
|
||||
The given XML is the same as the following D:
|
||||
|
||||
---
|
||||
auto select = new DropDownSelection(parent);
|
||||
select.addOption("Foo");
|
||||
select.addOption("Bar");
|
||||
auto page = new PageWidget(parent);
|
||||
page.name = "mypage";
|
||||
|
||||
select.addEventListener("change", (Event event) {
|
||||
page.setCurrentTab(event.intValue);
|
||||
});
|
||||
---
|
||||
+/
|
||||
module arsd.minigui_xml;
|
||||
|
||||
|
@ -41,7 +98,7 @@ void loadMiniguiPublicClasses() {
|
|||
|
||||
foreach(memberName; __traits(allMembers, mixin("arsd.minigui"))) static if(__traits(compiles, __traits(getMember, mixin("arsd.minigui"), memberName))) {
|
||||
alias Member = ident!(__traits(getMember, mixin("arsd.minigui"), memberName));
|
||||
static if(is(Member == class) && !isAbstractClass!Member && is(Member : Widget)) {
|
||||
static if(is(Member == class) && !isAbstractClass!Member && is(Member : Widget) && __traits(getProtection, Member) != "private") {
|
||||
widgetFactoryFunctions[memberName] = (string[string] args, Widget parent) {
|
||||
static if(is(Member : Dialog)) {
|
||||
return new Member();
|
||||
|
|
4
script.d
4
script.d
|
@ -406,7 +406,7 @@ class TokenStream(TextStream) {
|
|||
token.lineNumber = lineNumber;
|
||||
token.scriptFilename = scriptFilename;
|
||||
|
||||
if(text[0] == ' ' || text[0] == '\t' || text[0] == '\n') {
|
||||
if(text[0] == ' ' || text[0] == '\t' || text[0] == '\n' || text[0] == '\r') {
|
||||
advance(1);
|
||||
continue;
|
||||
} else if(text[0] >= '0' && text[0] <= '9') {
|
||||
|
@ -600,7 +600,7 @@ class TokenStream(TextStream) {
|
|||
if(symbol == "//") {
|
||||
// one line comment
|
||||
int pos = 0;
|
||||
while(pos < text.length && text[pos] != '\n')
|
||||
while(pos < text.length && text[pos] != '\n' && text[0] != '\r')
|
||||
pos++;
|
||||
advance(pos);
|
||||
continue mainLoop;
|
||||
|
|
204
simpledisplay.d
204
simpledisplay.d
|
@ -942,6 +942,7 @@ enum WindowFlags : int {
|
|||
alwaysOnTop = 2, ///
|
||||
alwaysOnBottom = 4, ///
|
||||
cannotBeActivated = 8, ///
|
||||
alwaysRequestMouseMotionEvents = 16, /// By default, simpledisplay will attempt to optimize mouse motion event reporting when it detects a remote connection, causing them to only be issued if input is grabbed (see: [SimpleWindow.grabInput]). This means doing hover effects and mouse game control on a remote X connection may not work right. Include this flag to override this optimization and always request the motion events. However btw, if you are doing mouse game control, you probably want to grab input anyway, and hover events are usually expendable! So think before you use this flag.
|
||||
dontAutoShow = 0x1000_0000, /// Don't automatically show window after creation; you will have to call `show()` manually.
|
||||
}
|
||||
|
||||
|
@ -3036,7 +3037,7 @@ char[] makeUtf8StringFromWindowsString(in wchar[] str, char[] buffer) {
|
|||
if(str.length == 0)
|
||||
return null;
|
||||
|
||||
auto got = WideCharToMultiByte(CP_UTF8, 0, str.ptr, str.length, buffer.ptr, buffer.length, null, null);
|
||||
auto got = WideCharToMultiByte(CP_UTF8, 0, str.ptr, cast(int) str.length, buffer.ptr, cast(int) buffer.length, null, null);
|
||||
if(got == 0) {
|
||||
if(GetLastError() == ERROR_INSUFFICIENT_BUFFER)
|
||||
throw new Exception("not enough buffer");
|
||||
|
@ -3049,7 +3050,7 @@ char[] makeUtf8StringFromWindowsString(in wchar[] str, char[] buffer) {
|
|||
version(Windows)
|
||||
string makeUtf8StringFromWindowsString(in wchar[] str) {
|
||||
char[] buffer;
|
||||
auto got = WideCharToMultiByte(CP_UTF8, 0, str.ptr, str.length, null, 0, null, null);
|
||||
auto got = WideCharToMultiByte(CP_UTF8, 0, str.ptr, cast(int) str.length, null, 0, null, null);
|
||||
buffer.length = got;
|
||||
|
||||
// it is unique because we just allocated it above!
|
||||
|
@ -3062,7 +3063,7 @@ string makeUtf8StringFromWindowsString(wchar* str) {
|
|||
auto got = WideCharToMultiByte(CP_UTF8, 0, str, -1, null, 0, null, null);
|
||||
buffer.length = got;
|
||||
|
||||
got = WideCharToMultiByte(CP_UTF8, 0, str, -1, buffer.ptr, buffer.length, null, null);
|
||||
got = WideCharToMultiByte(CP_UTF8, 0, str, -1, buffer.ptr, cast(int) buffer.length, null, null);
|
||||
if(got == 0) {
|
||||
if(GetLastError() == ERROR_INSUFFICIENT_BUFFER)
|
||||
throw new Exception("not enough buffer");
|
||||
|
@ -4306,9 +4307,9 @@ class OperatingSystemFont {
|
|||
struct ScreenPainter {
|
||||
CapableOfBeingDrawnUpon window;
|
||||
this(CapableOfBeingDrawnUpon window, NativeWindowHandle handle) {
|
||||
if(window.closed)
|
||||
throw new Exception("cannot draw on a closed window");
|
||||
this.window = window;
|
||||
if(window.closed)
|
||||
return; // null painter is now allowed so no need to throw anymore, this likely happens at the end of a program anyway
|
||||
currentClipRectangle = arsd.color.Rectangle(0, 0, window.width, window.height);
|
||||
if(window.activeScreenPainter !is null) {
|
||||
impl = window.activeScreenPainter;
|
||||
|
@ -4405,6 +4406,8 @@ struct ScreenPainter {
|
|||
/// Sets the clipping region for drawing. If width == 0 && height == 0, disabled clipping.
|
||||
void setClipRectangle(Point pt, int width, int height) {
|
||||
if(impl is null) return;
|
||||
if(pt == currentClipRectangle.upperLeft && width == currentClipRectangle.width && height == currentClipRectangle.height)
|
||||
return; // no need to do anything
|
||||
currentClipRectangle = arsd.color.Rectangle(pt, Size(width, height));
|
||||
transform(pt);
|
||||
|
||||
|
@ -6680,12 +6683,17 @@ version(X11) {
|
|||
bool backgroundIsNotTransparent = true;
|
||||
bool foregroundIsNotTransparent = true;
|
||||
|
||||
bool _penInitialized = false;
|
||||
Pen _activePen;
|
||||
|
||||
Color _outlineColor;
|
||||
Color _fillColor;
|
||||
|
||||
@property void pen(Pen p) {
|
||||
if(_penInitialized && p == _activePen) {
|
||||
return;
|
||||
}
|
||||
_penInitialized = true;
|
||||
_activePen = p;
|
||||
_outlineColor = p.color;
|
||||
|
||||
|
@ -6724,7 +6732,13 @@ version(X11) {
|
|||
cast(uint) p.color.b);
|
||||
}
|
||||
|
||||
RasterOp _currentRasterOp;
|
||||
bool _currentRasterOpInitialized = false;
|
||||
@property void rasterOp(RasterOp op) {
|
||||
if(_currentRasterOpInitialized && _currentRasterOp == op)
|
||||
return;
|
||||
_currentRasterOp = op;
|
||||
_currentRasterOpInitialized = true;
|
||||
int mode;
|
||||
final switch(op) {
|
||||
case RasterOp.normal:
|
||||
|
@ -6738,11 +6752,13 @@ version(X11) {
|
|||
}
|
||||
|
||||
|
||||
bool _fillColorInitialized = false;
|
||||
|
||||
@property void fillColor(Color c) {
|
||||
if(_fillColor == c)
|
||||
if(_fillColorInitialized && _fillColor == c)
|
||||
return; // already good, no need to waste time calling it
|
||||
_fillColor = c;
|
||||
_fillColorInitialized = true;
|
||||
if(c.a == 0) {
|
||||
backgroundIsNotTransparent = false;
|
||||
return;
|
||||
|
@ -6760,8 +6776,9 @@ version(X11) {
|
|||
void swapColors() {
|
||||
auto tmp = _fillColor;
|
||||
fillColor = _outlineColor;
|
||||
_activePen.color = tmp;
|
||||
pen(_activePen);
|
||||
auto newPen = _activePen;
|
||||
newPen.color = tmp;
|
||||
pen(newPen);
|
||||
}
|
||||
|
||||
void drawImage(int x, int y, Image i, int ix, int iy, int w, int h) {
|
||||
|
@ -7728,18 +7745,8 @@ version(X11) {
|
|||
// What would be ideal here is if they only were
|
||||
// selected if there was actually an event handler
|
||||
// for them...
|
||||
XSelectInput(display, window,
|
||||
EventMask.ExposureMask |
|
||||
EventMask.KeyPressMask |
|
||||
EventMask.KeyReleaseMask |
|
||||
EventMask.PropertyChangeMask |
|
||||
EventMask.FocusChangeMask |
|
||||
EventMask.StructureNotifyMask |
|
||||
EventMask.VisibilityChangeMask
|
||||
| EventMask.PointerMotionMask // FIXME: not efficient
|
||||
| EventMask.ButtonPressMask
|
||||
| EventMask.ButtonReleaseMask
|
||||
);
|
||||
|
||||
selectDefaultInput((customizationFlags & WindowFlags.alwaysRequestMouseMotionEvents)?true:false);
|
||||
|
||||
hiddenWindow:
|
||||
|
||||
|
@ -7766,6 +7773,26 @@ version(X11) {
|
|||
}
|
||||
}
|
||||
|
||||
void selectDefaultInput(bool forceIncludeMouseMotion) {
|
||||
auto mask = EventMask.ExposureMask |
|
||||
EventMask.KeyPressMask |
|
||||
EventMask.KeyReleaseMask |
|
||||
EventMask.PropertyChangeMask |
|
||||
EventMask.FocusChangeMask |
|
||||
EventMask.StructureNotifyMask |
|
||||
EventMask.VisibilityChangeMask
|
||||
| EventMask.ButtonPressMask
|
||||
| EventMask.ButtonReleaseMask
|
||||
;
|
||||
|
||||
// xshm is our shortcut for local connections
|
||||
if(Image.impl.xshmAvailable || forceIncludeMouseMotion)
|
||||
mask |= EventMask.PointerMotionMask;
|
||||
|
||||
XSelectInput(display, window, mask);
|
||||
}
|
||||
|
||||
|
||||
void setNetWMWindowType(Atom type) {
|
||||
Atom[2] atoms;
|
||||
|
||||
|
@ -8218,6 +8245,11 @@ version(X11) {
|
|||
break;
|
||||
case EventType.Expose:
|
||||
if(auto win = e.xexpose.window in SimpleWindow.nativeMapping) {
|
||||
// if it is closing from a popup menu, it can get
|
||||
// an Expose event right by the end and trigger a
|
||||
// BadDrawable error ... we'll just check
|
||||
// closed to handle that.
|
||||
if((*win).closed) break;
|
||||
if((*win).openglMode == OpenGlOptions.no) {
|
||||
bool doCopy = true;
|
||||
if (win.handleExpose !is null) doCopy = !win.handleExpose(e.xexpose.x, e.xexpose.y, e.xexpose.width, e.xexpose.height, e.xexpose.count);
|
||||
|
@ -11273,7 +11305,7 @@ mixin template ExperimentalTextComponent() {
|
|||
|
||||
struct TextIdentifyResult {
|
||||
InlineElement element;
|
||||
size_t offset;
|
||||
int offset;
|
||||
|
||||
private TextIdentifyResult fixupNewline() {
|
||||
if(element !is null && offset < element.text.length && element.text[offset] == '\n') {
|
||||
|
@ -11388,7 +11420,7 @@ mixin template ExperimentalTextComponent() {
|
|||
ie.text = arg[lastLineIndex .. $];
|
||||
ie.containingBlock = blocks[$-1];
|
||||
blocks[$-1].parts ~= ie.clone;
|
||||
caret = Caret(this, blocks[$-1].parts[$-1], blocks[$-1].parts[$-1].text.length);
|
||||
caret = Caret(this, blocks[$-1].parts[$-1], cast(int) blocks[$-1].parts[$-1].text.length);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -11424,9 +11456,10 @@ mixin template ExperimentalTextComponent() {
|
|||
if(x >= part.boundingBox.left && x < part.boundingBox.right && y >= part.boundingBox.top && y < part.boundingBox.bottom) {
|
||||
|
||||
// FIXME binary search
|
||||
size_t tidx;
|
||||
int tidx;
|
||||
int lastX;
|
||||
foreach_reverse(idx, lx; part.letterXs) {
|
||||
foreach_reverse(idxo, lx; part.letterXs) {
|
||||
int idx = cast(int) idxo;
|
||||
if(lx <= x) {
|
||||
if(lastX && lastX - x < x - lx)
|
||||
tidx = idx + 1;
|
||||
|
@ -11441,13 +11474,13 @@ mixin template ExperimentalTextComponent() {
|
|||
} else if(!exact) {
|
||||
// we're not in the box, but are we on the same line?
|
||||
if(y >= part.boundingBox.top && y < part.boundingBox.bottom)
|
||||
inexactMatch = TextIdentifyResult(part, x == 0 ? 0 : part.text.length);
|
||||
inexactMatch = TextIdentifyResult(part, x == 0 ? 0 : cast(int) part.text.length);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if(!exact && inexactMatch is TextIdentifyResult.init && blocks.length && blocks[$-1].parts.length)
|
||||
return TextIdentifyResult(blocks[$-1].parts[$-1], blocks[$-1].parts[$-1].text.length).fixupNewline;
|
||||
return TextIdentifyResult(blocks[$-1].parts[$-1], cast(int) blocks[$-1].parts[$-1].text.length).fixupNewline;
|
||||
|
||||
return exact ? TextIdentifyResult.init : inexactMatch.fixupNewline;
|
||||
}
|
||||
|
@ -11458,6 +11491,33 @@ mixin template ExperimentalTextComponent() {
|
|||
caret.offset = result.offset;
|
||||
}
|
||||
|
||||
void selectToPixelCoordinates(int x, int y) {
|
||||
auto result = identify(x, y);
|
||||
|
||||
if(y < caretLastDrawnY1) {
|
||||
// on a previous line, carat is selectionEnd
|
||||
selectionEnd = caret;
|
||||
|
||||
selectionStart = Caret(this, result.element, result.offset);
|
||||
} else if(y > caretLastDrawnY2) {
|
||||
// on a later line
|
||||
selectionStart = caret;
|
||||
|
||||
selectionEnd = Caret(this, result.element, result.offset);
|
||||
} else {
|
||||
// on the same line...
|
||||
if(x <= caretLastDrawnX) {
|
||||
selectionEnd = caret;
|
||||
selectionStart = Caret(this, result.element, result.offset);
|
||||
} else {
|
||||
selectionStart = caret;
|
||||
selectionEnd = Caret(this, result.element, result.offset);
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/// Call this if the inputs change. It will reflow everything
|
||||
void redoLayout(ScreenPainter painter) {
|
||||
//painter.setClipRectangle(boundingBox);
|
||||
|
@ -11637,7 +11697,7 @@ mixin template ExperimentalTextComponent() {
|
|||
/// Caret movement api
|
||||
/// These should give the user a logical result based on what they see on screen...
|
||||
/// thus they locate predominately by *pixels* not char index. (These will generally coincide with monospace fonts tho!)
|
||||
void moveUp(ref Caret caret) {
|
||||
void moveUp() {
|
||||
if(caret.inlineElement is null) return;
|
||||
auto x = caret.inlineElement.xOfIndex(caret.offset);
|
||||
auto y = caret.inlineElement.boundingBox.top + 2;
|
||||
|
@ -11653,7 +11713,7 @@ mixin template ExperimentalTextComponent() {
|
|||
caret.offset = i.offset;
|
||||
}
|
||||
}
|
||||
void moveDown(ref Caret caret) {
|
||||
void moveDown() {
|
||||
if(caret.inlineElement is null) return;
|
||||
auto x = caret.inlineElement.xOfIndex(caret.offset);
|
||||
auto y = caret.inlineElement.boundingBox.bottom - 2;
|
||||
|
@ -11666,7 +11726,7 @@ mixin template ExperimentalTextComponent() {
|
|||
caret.offset = i.offset;
|
||||
}
|
||||
}
|
||||
void moveLeft(ref Caret caret) {
|
||||
void moveLeft() {
|
||||
if(caret.inlineElement is null) return;
|
||||
if(caret.offset)
|
||||
caret.offset--;
|
||||
|
@ -11675,13 +11735,13 @@ mixin template ExperimentalTextComponent() {
|
|||
if(p) {
|
||||
caret.inlineElement = p;
|
||||
if(p.text.length && p.text[$-1] == '\n')
|
||||
caret.offset = p.text.length - 1;
|
||||
caret.offset = cast(int) p.text.length - 1;
|
||||
else
|
||||
caret.offset = p.text.length;
|
||||
caret.offset = cast(int) p.text.length;
|
||||
}
|
||||
}
|
||||
}
|
||||
void moveRight(ref Caret caret) {
|
||||
void moveRight() {
|
||||
if(caret.inlineElement is null) return;
|
||||
if(caret.offset < caret.inlineElement.text.length && caret.inlineElement.text[caret.offset] != '\n') {
|
||||
caret.offset++;
|
||||
|
@ -11693,7 +11753,7 @@ mixin template ExperimentalTextComponent() {
|
|||
}
|
||||
}
|
||||
}
|
||||
void moveHome(ref Caret caret) {
|
||||
void moveHome() {
|
||||
if(caret.inlineElement is null) return;
|
||||
auto x = 0;
|
||||
auto y = caret.inlineElement.boundingBox.top + 2;
|
||||
|
@ -11705,7 +11765,7 @@ mixin template ExperimentalTextComponent() {
|
|||
caret.offset = i.offset;
|
||||
}
|
||||
}
|
||||
void moveEnd(ref Caret caret) {
|
||||
void moveEnd() {
|
||||
if(caret.inlineElement is null) return;
|
||||
auto x = int.max;
|
||||
auto y = caret.inlineElement.boundingBox.top + 2;
|
||||
|
@ -11732,7 +11792,7 @@ mixin template ExperimentalTextComponent() {
|
|||
if(blocks.length) {
|
||||
auto parts = blocks[$-1].parts;
|
||||
if(parts.length) {
|
||||
caret = Caret(this, parts[$-1], parts[$-1].text.length);
|
||||
caret = Caret(this, parts[$-1], cast(int) parts[$-1].text.length);
|
||||
} else {
|
||||
caret = Caret.init;
|
||||
}
|
||||
|
@ -11748,33 +11808,42 @@ mixin template ExperimentalTextComponent() {
|
|||
assert(selectionEnd.inlineElement !is null);
|
||||
|
||||
auto at = selectionStart.inlineElement;
|
||||
auto atOffset = selectionStart.offset;
|
||||
while(at) {
|
||||
at.text = at.text[atOffset .. $];
|
||||
if(atOffset < at.letterXs.length)
|
||||
at.letterXs = at.letterXs[atOffset .. $];
|
||||
|
||||
if(at is selectionEnd.inlineElement) {
|
||||
selectionEnd.offset -= atOffset;
|
||||
at.text = at.text[selectionEnd.offset .. $];
|
||||
if(selectionEnd.offset < at.letterXs.length)
|
||||
at.letterXs = at.letterXs[selectionEnd.offset .. $];
|
||||
selectionEnd.offset = 0;
|
||||
break;
|
||||
} else {
|
||||
auto cfd = at;
|
||||
if(selectionEnd.inlineElement is at) {
|
||||
// same element, need to chop out
|
||||
at.text = at.text[0 .. selectionStart.offset] ~ at.text[selectionEnd.offset .. $];
|
||||
at.letterXs = at.letterXs[0 .. selectionStart.offset] ~ at.letterXs[selectionEnd.offset .. $];
|
||||
selectionEnd.offset -= selectionEnd.offset - selectionStart.offset;
|
||||
} else {
|
||||
// different elements, we can do it with slicing
|
||||
at.text = at.text[0 .. selectionStart.offset];
|
||||
if(selectionStart.offset < at.letterXs.length)
|
||||
at.letterXs = at.letterXs[0 .. selectionStart.offset];
|
||||
|
||||
at = at.getNextInlineElement();
|
||||
if(at)
|
||||
atOffset = at.text.length;
|
||||
if(cfd.text.length == 0) {
|
||||
// and remove cfd
|
||||
for(size_t a = 0; a < cfd.containingBlock.parts.length; a++) {
|
||||
if(cfd.containingBlock.parts[a] is cfd) {
|
||||
for(size_t i = a; i < cfd.containingBlock.parts.length - 1; i++)
|
||||
cfd.containingBlock.parts[i] = cfd.containingBlock.parts[i + 1];
|
||||
cfd.containingBlock.parts = cfd.containingBlock.parts[0 .. $-1];
|
||||
at = at.getNextInlineElement();
|
||||
|
||||
while(at) {
|
||||
if(at is selectionEnd.inlineElement) {
|
||||
at.text = at.text[selectionEnd.offset .. $];
|
||||
if(selectionEnd.offset < at.letterXs.length)
|
||||
at.letterXs = at.letterXs[selectionEnd.offset .. $];
|
||||
selectionEnd.offset = 0;
|
||||
break;
|
||||
} else {
|
||||
auto cfd = at;
|
||||
cfd.text = null; // delete the whole thing
|
||||
|
||||
at = at.getNextInlineElement();
|
||||
|
||||
if(cfd.text.length == 0) {
|
||||
// and remove cfd
|
||||
for(size_t a = 0; a < cfd.containingBlock.parts.length; a++) {
|
||||
if(cfd.containingBlock.parts[a] is cfd) {
|
||||
for(size_t i = a; i < cfd.containingBlock.parts.length - 1; i++)
|
||||
cfd.containingBlock.parts[i] = cfd.containingBlock.parts[i + 1];
|
||||
cfd.containingBlock.parts = cfd.containingBlock.parts[0 .. $-1];
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -11886,7 +11955,7 @@ mixin template ExperimentalTextComponent() {
|
|||
auto prev = e.getPreviousInlineElement();
|
||||
if(prev is null)
|
||||
return;
|
||||
auto newOffset = prev.text.length;
|
||||
auto newOffset = cast(int) prev.text.length;
|
||||
tryMerge(prev, e);
|
||||
caret.inlineElement = prev;
|
||||
caret.offset = prev is null ? 0 : newOffset;
|
||||
|
@ -11904,11 +11973,14 @@ mixin template ExperimentalTextComponent() {
|
|||
invalidateLayout();
|
||||
}
|
||||
void delete_() {
|
||||
auto after = caret;
|
||||
moveRight(after);
|
||||
if(caret != after) {
|
||||
caret = after;
|
||||
backspace();
|
||||
if(selectionStart !is selectionEnd)
|
||||
deleteSelection();
|
||||
else {
|
||||
auto before = caret;
|
||||
moveRight();
|
||||
if(caret != before) {
|
||||
backspace();
|
||||
}
|
||||
}
|
||||
|
||||
invalidateLayout();
|
||||
|
@ -11963,7 +12035,7 @@ mixin template ExperimentalTextComponent() {
|
|||
struct Caret {
|
||||
TextLayout layout;
|
||||
InlineElement inlineElement;
|
||||
size_t offset;
|
||||
int offset;
|
||||
}
|
||||
|
||||
enum TextFormat : ushort {
|
||||
|
|
Loading…
Reference in New Issue