some browser jam stuff

This commit is contained in:
Adam D. Ruppe 2024-09-13 22:02:07 -04:00
parent 21c8eb6cbd
commit 6e4e2966ca
3 changed files with 125 additions and 8 deletions

41
dom.d
View File

@ -3078,7 +3078,7 @@ class Element : DomParent {
/* done */
_computedStyle = new CssStyle(null, style); // gives at least something to work with
_computedStyle = computedStyleFactory(this);
}
return _computedStyle;
}
@ -7640,6 +7640,24 @@ Element[] removeDuplicates(Element[] input) {
// done with CSS selector handling
/++
This delegate is called if you call [Element.computedStyle] to attach an object to the element
that holds stylesheet information. You can rebind it to something else to return a subclass
if you want to hold more per-element extension data than the normal computed style object holds
(e.g. layout info as well).
The default is `return new CssStyle(null, element.style);`
History:
Added September 13, 2024 (dub v11.6)
+/
CssStyle function(Element e) computedStyleFactory = &defaultComputedStyleFactory;
/// ditto
CssStyle defaultComputedStyleFactory(Element e) {
return new CssStyle(null, e.style); // gives at least something to work with
}
// FIXME: use the better parser from html.d
/// This is probably not useful to you unless you're writing a browser or something like that.
@ -7726,7 +7744,7 @@ class CssStyle {
if(value is null)
return getValue(name);
else
return setValue(name, value, 0x02000000 /* inline specificity */);
return setValue(name, value, Specificity(0x02000000) /* inline specificity */);
}
/// takes dash style name
@ -8709,11 +8727,13 @@ void fillForm(T)(Form form, T obj, string name) {
History:
Added March 25, 2022 (dub v10.8)
The `stripLeadingAndTrailing` argument was added September 13, 2024 (dub v11.6).
+/
string normalizeWhitespace(string text) {
string normalizeWhitespace(string text, bool stripLeadingAndTrailing = true) {
string ret;
ret.reserve(text.length);
bool lastWasWhite = true;
bool lastWasWhite = stripLeadingAndTrailing;
foreach(char ch; text) {
if(ch == ' ' || ch == '\t' || ch == '\n' || ch == '\r') {
if(lastWasWhite)
@ -8727,12 +8747,23 @@ string normalizeWhitespace(string text) {
ret ~= ch;
}
return ret.stripRight;
if(stripLeadingAndTrailing)
return ret.stripRight;
else {
/+
if(lastWasWhite && (ret.length == 0 || ret[$-1] != ' '))
ret ~= ' ';
+/
return ret;
}
}
unittest {
assert(normalizeWhitespace(" foo ") == "foo");
assert(normalizeWhitespace(" f\n \t oo ") == "f oo");
assert(normalizeWhitespace(" foo ", false) == " foo ");
assert(normalizeWhitespace(" foo ", false) == " foo ");
assert(normalizeWhitespace("\nfoo", false) == " foo");
}
unittest {

View File

@ -1560,11 +1560,23 @@ class Widget : ReflectableProperties {
+/
final @property inout(Window) parentWindow() inout @nogc nothrow pure { return _parentWindow; }
private @property void parentWindow(Window parent) {
auto old = _parentWindow;
_parentWindow = parent;
newParentWindow(old, _parentWindow);
foreach(child; children)
child.parentWindow = parent; // please note that this is recursive
}
/++
Called when the widget has been added to or remove from a parent window.
Note that either oldParent and/or newParent may be null any time this is called.
History:
Added September 13, 2024
+/
protected void newParentWindow(Window oldParent, Window newParent) {}
/++
Returns the list of the widget's children.
@ -12093,6 +12105,7 @@ class TextDisplayHelper : Widget {
with(l.selection()) {
if(!isEmpty()) {
getPrimarySelection(parentWindow.win, (in char[] txt) {
// import std.stdio; writeln("txt: ", txt, " sel: ", getContentString);
if(txt.length) {
preservedPrimaryText = txt.idup;
// writeln(preservedPrimaryText);
@ -12425,6 +12438,8 @@ class TextDisplayHelper : Widget {
parentWindow.win.getPrimarySelection((txt) {
doStateCheckpoint();
// import arsd.core; writeln(txt);writeln(l.selection.getContentString);writeln(preservedPrimaryText);
if(txt == l.selection.getContentString && preservedPrimaryText.length)
l.selection.replaceContent(preservedPrimaryText);
else
@ -12910,7 +12925,10 @@ abstract class EditableTextWidget : EditableTextWidgetParent {
this.tabStop = false;
smw.tabStop = false;
tdh = textDisplayHelperFactory(textLayout, smw);
}
override void newParentWindow(Window old, Window n) {
if(n is null) return;
this.parentWindow.addEventListener((scope DpiChangedEvent dce) {
if(textLayout) {
if(auto style = cast(TextDisplayHelper.MyTextStyle) textLayout.defaultStyle()) {
@ -13453,6 +13471,9 @@ abstract class GenericListViewWidget : Widget {
private ScrollMessageWidget smw;
private GenericListViewWidgetInner inner;
/++
+/
abstract GenericListViewItem itemFactory(Widget parent);
// in device-dependent pixels
/++
@ -13508,9 +13529,7 @@ abstract class GenericListViewWidget : Widget {
private GenericListViewItem[] items;
}
/++
+/
/// ditto
abstract class GenericListViewItem : Widget {
/++
+/
@ -13544,6 +13563,52 @@ abstract class GenericListViewItem : Widget {
}
}
///
unittest {
import arsd.minigui;
import std.conv;
void main() {
auto mw = new MainWindow();
static class MyListViewItem : GenericListViewItem {
this(Widget parent) {
super(parent);
label = new TextLabel("unloaded", TextAlignment.Left, this);
button = new Button("Click", this);
button.addEventListener("triggered", (){
messageBox(text("clicked ", currentIndexLoaded()));
});
}
override void showItem(int idx) {
label.label = "Item " ~ to!string(idx);
}
TextLabel label;
Button button;
}
auto widget = new class GenericListViewWidget {
this() {
super(mw);
}
override GenericListViewItem itemFactory(Widget parent) {
return new MyListViewItem(parent);
}
override Size itemSize() {
return Size(0, scaleWithDpi(80));
}
};
widget.setItemCount(5000);
mw.loop();
}
}
private class GenericListViewWidgetInner : Widget {
this(GenericListViewWidget glvw, ScrollMessageWidget smw) {
super(smw);

View File

@ -1212,6 +1212,8 @@ class TextLayouter {
Starts from the given selection and moves in the direction to find next.
Returns true if found.
NOT IMPLEMENTED use a selection instead
+/
FindResult find(int selectionId, in const(char)[] text, bool direction, bool wraparound) {
return FindResult.NotFound;
@ -1756,6 +1758,25 @@ class TextLayouter {
return idx;
}
/++
History:
Added September 13, 2024
+/
const(TextStyle) styleAtPoint(Point p) {
TextStyle s;
getInternalSegments(delegate bool(size_t segmentIndex, scope ref Segment segment) {
if(segment.boundingBox.contains(p)) {
s = stylePalette[segment.styleInformationIndex];
return false;
}
return true;
}, Rectangle(p, Size(1, 1)));
return s;
}
private StyleHandle getInsertionStyleAt(int offset) {
assert(offset >= 0 && offset < text.length);
/+