mirror of https://github.com/adamdruppe/arsd.git
more hacky bugfixes, no actual fundamental flaw fixes :(
This commit is contained in:
parent
d3c7f3fddc
commit
1cfacea360
48
minigui.d
48
minigui.d
|
@ -1835,6 +1835,17 @@ class ScrollableWidget : Widget {
|
|||
horizontalScrollBar = new HorizontalScrollbar(horizontalScrollbarHolder);
|
||||
verticalScrollBar = new VerticalScrollbar(verticalScrollbarHolder);
|
||||
|
||||
// TOTAL HACKS
|
||||
horizontalScrollBar.addEventListener("mousedown", (Event event) { event.preventDefault(); });
|
||||
verticalScrollBar.addEventListener("mousedown", (Event event) { event.preventDefault(); });
|
||||
horizontalScrollBar.addEventListener("mousemove", (Event event) { event.preventDefault(); });
|
||||
verticalScrollBar.addEventListener("mousemove", (Event event) { event.preventDefault(); });
|
||||
|
||||
/*
|
||||
clientAreaHolder = new FixedPosition(this);
|
||||
clientArea = new ScrollableClientWidget(clientAreaHolder);
|
||||
*/
|
||||
|
||||
horizontalScrollbarHolder.showing_ = false;
|
||||
verticalScrollbarHolder.showing_ = false;
|
||||
|
||||
|
@ -1894,6 +1905,11 @@ class ScrollableWidget : Widget {
|
|||
|
||||
VerticalScrollbar verticalScrollBar;
|
||||
HorizontalScrollbar horizontalScrollBar;
|
||||
|
||||
/*
|
||||
FixedPosition clientAreaHolder;
|
||||
Widget clientArea;
|
||||
*/
|
||||
}
|
||||
|
||||
version(custom_widgets)
|
||||
|
@ -1910,6 +1926,13 @@ class ScrollableWidget : Widget {
|
|||
verticalScrollbarHolder.x = this.width - verticalScrollBar.minWidth();
|
||||
verticalScrollbarHolder.y = 0 + 2;
|
||||
|
||||
/*
|
||||
clientAreaHolder.x = 0;
|
||||
clientAreaHolder.y = 0;
|
||||
clientAreaHolder.width = this.width - verticalScrollBar.width;
|
||||
clientAreaHolder.height = this.height - horizontalScrollBar.height;
|
||||
*/
|
||||
|
||||
if(contentWidth_ <= this.width)
|
||||
scrollOrigin_.x = 0;
|
||||
if(contentHeight_ <= this.height)
|
||||
|
@ -2182,7 +2205,7 @@ class ScrollableWidget : Widget {
|
|||
painter.originX = painter.originX - scrollOrigin.x;
|
||||
painter.originY = painter.originY - scrollOrigin.y;
|
||||
if(force || redrawRequested) {
|
||||
painter.setClipRectangle(scrollOrigin, viewportWidth(), viewportHeight());
|
||||
painter.setClipRectangle(scrollOrigin + Point(2, 2) /* border */, viewportWidth() - 4 /* border */, viewportHeight() - 4 /* border */);
|
||||
|
||||
//erase(painter); // we paintFrameAndBackground above so no need
|
||||
paint(painter);
|
||||
|
@ -2199,6 +2222,17 @@ class ScrollableWidget : Widget {
|
|||
}
|
||||
}
|
||||
|
||||
/*
|
||||
class ScrollableClientWidget : Widget {
|
||||
this(Widget parent) {
|
||||
super(parent);
|
||||
}
|
||||
override void paint(ScreenPainter p) {
|
||||
parent.paint(p);
|
||||
}
|
||||
}
|
||||
*/
|
||||
|
||||
///
|
||||
abstract class ScrollbarBase : Widget {
|
||||
///
|
||||
|
@ -5434,6 +5468,12 @@ abstract class EditableTextWidget : EditableTextWidgetParent {
|
|||
version(custom_widgets)
|
||||
override void paintFrameAndBackground(ScreenPainter painter) {
|
||||
this.draw3dFrame(painter, FrameStyle.sunk, Color.white);
|
||||
if(horizontalScrollbarHolder.showing && verticalScrollbarHolder.showing) {
|
||||
// just paint over the lower-right corner
|
||||
painter.outlineColor = windowBackgroundColor;
|
||||
painter.fillColor = windowBackgroundColor;
|
||||
painter.drawRectangle(Point(width - 16, height - 16), Size(16, 16));
|
||||
}
|
||||
}
|
||||
|
||||
version(win32_widgets) { /* will do it with Windows calls in the classes */ }
|
||||
|
@ -5480,9 +5520,11 @@ abstract class EditableTextWidget : EditableTextWidgetParent {
|
|||
super.defaultEventHandler_mousedown(ev);
|
||||
if(parentWindow.win.closed) return;
|
||||
if(ev.button == MouseButton.left) {
|
||||
if(textLayout.selectNone())
|
||||
redraw();
|
||||
textLayout.moveCaretToPixelCoordinates(ev.clientX, ev.clientY);
|
||||
this.focus();
|
||||
this.parentWindow.win.grabInput();
|
||||
//this.parentWindow.win.grabInput();
|
||||
} else if(ev.button == MouseButton.middle) {
|
||||
static if(UsingSimpledisplayX11) {
|
||||
getPrimarySelection(parentWindow.win, (txt) {
|
||||
|
@ -5498,7 +5540,7 @@ abstract class EditableTextWidget : EditableTextWidgetParent {
|
|||
|
||||
version(custom_widgets)
|
||||
override void defaultEventHandler_mouseup(Event ev) {
|
||||
this.parentWindow.win.releaseInputGrab();
|
||||
//this.parentWindow.win.releaseInputGrab();
|
||||
super.defaultEventHandler_mouseup(ev);
|
||||
}
|
||||
|
||||
|
|
252
simpledisplay.d
252
simpledisplay.d
|
@ -6343,6 +6343,15 @@ struct ScreenPainter {
|
|||
impl.drawRectangle(upperLeft.x, upperLeft.y, width, height);
|
||||
}
|
||||
|
||||
/// ditto
|
||||
void drawRectangle(Point upperLeft, Size size) {
|
||||
if(impl is null) return;
|
||||
if(isClipped(upperLeft, size.width, size.height)) return;
|
||||
transform(upperLeft);
|
||||
impl.drawRectangle(upperLeft.x, upperLeft.y, size.width, size.height);
|
||||
}
|
||||
|
||||
/// ditto
|
||||
void drawRectangle(Point upperLeft, Point lowerRightInclusive) {
|
||||
if(impl is null) return;
|
||||
if(isClipped(upperLeft, lowerRightInclusive + Point(1, 1))) return;
|
||||
|
@ -8455,6 +8464,7 @@ version(X11) {
|
|||
/// for cross-platform compatibility.
|
||||
//__gshared string xfontstr = "-*-dejavu sans-medium-r-*-*-12-*-*-*-*-*-*-*";
|
||||
__gshared string xfontstr = "-*-lucida-medium-r-normal-sans-12-*-*-*-*-*-*-*";
|
||||
//__gshared string xfontstr = "-*-fixed-medium-r-*-*-14-*-*-*-*-*-*-*";
|
||||
|
||||
alias int delegate(XEvent) NativeEventHandler;
|
||||
alias Window NativeWindowHandle;
|
||||
|
@ -13014,229 +13024,17 @@ version(X11) {
|
|||
}
|
||||
|
||||
mixin template ExperimentalTextComponent2() {
|
||||
|
||||
enum TextFormat : ushort {
|
||||
// decorations
|
||||
underline = 1,
|
||||
strikethrough = 2,
|
||||
|
||||
// font selectors
|
||||
|
||||
bold = 0x4000 | 1, // weight 700
|
||||
light = 0x4000 | 2, // weight 300
|
||||
veryBoldOrLight = 0x4000 | 4, // weight 100 with light, weight 900 with bold
|
||||
// bold | light is really invalid but should give weight 500
|
||||
// veryBoldOrLight without one of the others should just give the default for the font; it should be ignored.
|
||||
|
||||
italic = 0x4000 | 8,
|
||||
smallcaps = 0x4000 | 16,
|
||||
}
|
||||
|
||||
|
||||
struct Decoration {
|
||||
ushort id;
|
||||
Color foreground;
|
||||
Color background;
|
||||
ushort textFormat;
|
||||
void* font;
|
||||
}
|
||||
|
||||
Decoration[] decorations;
|
||||
|
||||
struct TextState {
|
||||
char[] text;
|
||||
int[] x;
|
||||
int[] y;
|
||||
ushort[] decorationId;
|
||||
int length;
|
||||
|
||||
int caret;
|
||||
|
||||
void makeGap(int where, int minLength) {
|
||||
int gapSize = 0;
|
||||
int at = where;
|
||||
while(at < text.length && text[at] == 0xff) {
|
||||
at++;
|
||||
gapSize++;
|
||||
}
|
||||
|
||||
if(gapSize >= minLength)
|
||||
return;
|
||||
|
||||
// try to gather gap from behind us, if any
|
||||
/*
|
||||
at = where - 32;
|
||||
if(at < 0)
|
||||
at = 0;
|
||||
|
||||
while(at < where - 1) {
|
||||
if(text[at] == 0xff) {
|
||||
text[at] = text[at + 1];
|
||||
x[at] = x[at + 1];
|
||||
y[at] = y[at + 1];
|
||||
decorationId[at] = decorationId[at + 1];
|
||||
text[at + 1] = 0xff;
|
||||
gapSize++;
|
||||
}
|
||||
at++;
|
||||
}
|
||||
|
||||
if(gapSize >= minLength)
|
||||
return;
|
||||
*/
|
||||
keep_trying:
|
||||
at = where;
|
||||
while(at + 1 < text.length) {
|
||||
// FIXME it needs to work on a whole block, not just one char
|
||||
if(text[at + 1] == 0xff) {
|
||||
text[at + 1] = text[at];
|
||||
x[at + 1] = x[at];
|
||||
y[at + 1] = y[at];
|
||||
decorationId[at + 1] = decorationId[at];
|
||||
text[at] = 0xff;
|
||||
gapSize++;
|
||||
if(gapSize >= minLength)
|
||||
return;
|
||||
}
|
||||
at++;
|
||||
}
|
||||
|
||||
if(gapSize < minLength) {
|
||||
auto increase = 16;
|
||||
if(minLength - gapSize > 16)
|
||||
increase = minLength - gapSize;
|
||||
text.length += increase;
|
||||
x.length += increase;
|
||||
y.length += increase;
|
||||
decorationId.length += increase;
|
||||
text[$ - increase .. $] = 0xff;
|
||||
goto keep_trying;
|
||||
}
|
||||
}
|
||||
|
||||
void insert(dchar c) {
|
||||
makeGap(caret, 1);
|
||||
text[caret] = cast(char) c;
|
||||
caret++;
|
||||
length++;
|
||||
layout(caret - 1, cast(int) text.length, false);
|
||||
}
|
||||
|
||||
string toPlainText() {
|
||||
string s;
|
||||
s.reserve(length);
|
||||
foreach(char ch; text)
|
||||
if(ch != 0xff)
|
||||
s ~= ch;
|
||||
return s;
|
||||
}
|
||||
|
||||
void resetContents(in char[] to) {
|
||||
if(text.length < to.length * 2) {
|
||||
text.length = to.length * 2;
|
||||
x.length = text.length;
|
||||
y.length = text.length;
|
||||
decorationId.length = text.length;
|
||||
}
|
||||
int textPos = 0;
|
||||
int skipped = 0;
|
||||
foreach(ch; to) {
|
||||
if(ch == 13) {
|
||||
++skipped;
|
||||
continue;
|
||||
}
|
||||
text[textPos++] = ch;
|
||||
text[textPos++] = 0xff;
|
||||
}
|
||||
text[textPos .. $] = 0xff;
|
||||
length = cast(int) to.length - skipped;
|
||||
|
||||
decorationId[0 .. length] = 0;
|
||||
|
||||
layout(0, text.length, true);
|
||||
}
|
||||
|
||||
int lineHeight = 14;
|
||||
int letterWidth = 7;
|
||||
int tabStop = 4;
|
||||
|
||||
void layout(int start, int end, bool forceAll) {
|
||||
int x = 0, y = 0;
|
||||
foreach(idx, char ch; text[start .. end]) {
|
||||
if(ch == 0xff)
|
||||
continue;
|
||||
if(!forceAll && this.x[start + idx] == x && this.y[start + idx] == y)
|
||||
break; // seems to already be done!
|
||||
this.x[start + idx] = x;
|
||||
this.y[start + idx] = y;
|
||||
|
||||
// FIXME unicode
|
||||
|
||||
if(ch == '\n') {
|
||||
x = 0;
|
||||
y += lineHeight;
|
||||
} else if(ch == '\t') {
|
||||
x += x % (letterWidth * tabStop);
|
||||
} else {
|
||||
x += letterWidth;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void drawInto(ScreenPainter painter, int dx, int dy, int sx, int sy, int width, int height) {
|
||||
//char[6] buffer;
|
||||
// FIXME unicode
|
||||
|
||||
painter.outlineColor = Color.white;
|
||||
painter.fillColor = Color.white;
|
||||
painter.drawRectangle(Point(dx, dy), width, height);
|
||||
|
||||
painter.outlineColor = Color.black;
|
||||
|
||||
if(length == 0)
|
||||
return;
|
||||
|
||||
int startingIdx = 0;
|
||||
if(sx > 0 || sy > 0) {
|
||||
int lastSearched = text.length;
|
||||
// binary search till we get the first visible item
|
||||
startingIdx = text.length / 2;
|
||||
keep_searching:
|
||||
while(startingIdx >= 0 && text[startingIdx] == 0xff)
|
||||
--startingIdx;
|
||||
while(text[startingIdx] == 0xff && startingIdx < text.length)
|
||||
++startingIdx;
|
||||
if(startingIdx == text.length)
|
||||
assert(0); // we're apparently empty! why didn't length == 0?
|
||||
|
||||
if(this.x[startingIdx] > sx || this.y[startingIdx] > sy) {
|
||||
// FIXME
|
||||
// too far ahead, search backward
|
||||
lastSearched = startingIdx;
|
||||
startingIdx = startingIdx / 2;
|
||||
goto keep_searching;
|
||||
} else {
|
||||
// this is probably good enough but let's try to be more precise
|
||||
//startingIdx = (lastSearched - startingIdx) / 2;
|
||||
//goto keep_searching;
|
||||
}
|
||||
}
|
||||
|
||||
foreach(idx, char ch; text[startingIdx .. $]) {
|
||||
if(ch == 0xff)
|
||||
continue;
|
||||
int drawX = dx + this.x[startingIdx + idx] - sx;
|
||||
int drawY = dy + this.y[startingIdx + idx] - sy;
|
||||
|
||||
if(drawX - dx > width)
|
||||
continue;
|
||||
if(drawY - dy > height)
|
||||
break;
|
||||
|
||||
painter.drawText(Point(drawX, drawY), "" ~ ch);
|
||||
}
|
||||
}
|
||||
}
|
||||
/+
|
||||
Stage 1: get it working monospace
|
||||
Stage 2: use proportional font
|
||||
Stage 3: allow changes in inline style
|
||||
Stage 4: allow new fonts and sizes in the middle
|
||||
Stage 5: optimize gap buffer
|
||||
Stage 6: optimize layout
|
||||
Stage 7: word wrap
|
||||
Stage 8: justification
|
||||
Stage 9: editing, selection, etc.
|
||||
+/
|
||||
}
|
||||
|
||||
|
||||
|
@ -14097,8 +13895,12 @@ mixin template ExperimentalTextComponent() {
|
|||
moveDocumentStart(selectionStart);
|
||||
moveDocumentEnd(selectionEnd);
|
||||
}
|
||||
void selectNone() {
|
||||
selectionStart = selectionEnd = Caret.init;
|
||||
bool selectNone() {
|
||||
if(selectionStart != selectionEnd) {
|
||||
selectionStart = selectionEnd = Caret.init;
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
/// Rich text editing api. These allow you to manipulate the meta data of the current element and add new elements.
|
||||
|
|
Loading…
Reference in New Issue