more updates. hidecursor by ketmar

This commit is contained in:
Adam D. Ruppe 2015-12-07 21:07:58 -05:00
parent c9a3f35bf9
commit 65b3b06f6d
7 changed files with 219 additions and 38 deletions

7
cgi.d
View File

@ -2523,8 +2523,15 @@ bool isCgiRequestMethod(string s) {
/// If you want to use a subclass of Cgi with generic main, use this mixin.
mixin template CustomCgiMain(CustomCgi, alias fun, long maxContentLength = defaultMaxContentLength) if(is(CustomCgi : Cgi)) {
// kinda hacky - the T... is passed to Cgi's constructor in standard cgi mode, and ignored elsewhere
mixin CustomCgiMainImpl!(CustomCgi, fun, maxContentLength) customCgiMainImpl_;
void main(string[] args) {
customCgiMainImpl_.cgiMainImpl(args);
}
}
mixin template CustomCgiMainImpl(CustomCgi, alias fun, long maxContentLength = defaultMaxContentLength) if(is(CustomCgi : Cgi)) {
void cgiMainImpl(string[] args) {
// we support command line thing for easy testing everywhere

View File

@ -180,13 +180,16 @@ final class OpenGlTexture {
void draw(float x, float y, int width = 0, int height = 0, float rotation = 0.0, Color bg = Color.white) {
glPushMatrix();
glTranslatef(x, y, 0);
glRotatef(rotation, 0,0, 1);
if(width == 0)
width = this.originalImageWidth;
if(height == 0)
height = this.originalImageHeight;
glTranslatef(cast(float) width / 2, cast(float) height / 2, 0);
glRotatef(rotation, 0, 0, 1);
glTranslatef(cast(float) -width / 2, cast(float) -height / 2, 0);
glColor4f(cast(float)bg.r/255.0, cast(float)bg.g/255.0, cast(float)bg.b/255.0, cast(float)bg.a / 255.0);
glBindTexture(GL_TEXTURE_2D, _tex);
glBegin(GL_QUADS);
@ -212,6 +215,9 @@ final class OpenGlTexture {
int originalImageWidth() { return _width; }
int originalImageHeight() { return _height; } /// ditto
// explicitly undocumented, i might remove this
TrueColorImage from;
/// Make a texture from an image.
this(TrueColorImage from) {
assert(from.width > 0 && from.height > 0);
@ -219,6 +225,8 @@ final class OpenGlTexture {
_width = from.width;
_height = from.height;
this.from = from;
auto _texWidth = _width;
auto _texHeight = _height;
@ -328,3 +336,28 @@ void rotateAboutAxis(
yp = v * (u*x + v*y + w*z) * (1 - cos(theta)) + y * cos(theta) + (w*x - u*z) * sin(theta);
zp = w * (u*x + v*y + w*z) * (1 - cos(theta)) + z * cos(theta) + (-v*x + u*y) * sin(theta);
}
void rotateAboutPoint(
float theta, // in RADIANS
float originX, float originY,
float rotatingX, float rotatingY,
out float xp, out float yp)
{
if(theta == 0) {
xp = rotatingX;
yp = rotatingY;
return;
}
rotatingX -= originX;
rotatingY -= originY;
float s = sin(theta);
float c = cos(theta);
float x = rotatingX * c - rotatingY * s;
float y = rotatingX * s + rotatingY * c;
xp = x + originX;
yp = y + originY;
}

View File

@ -736,7 +736,7 @@ class HttpRequest {
requestParameters.ssl = parts.scheme == "https";
if(parts.port == 0)
requestParameters.port = requestParameters.ssl ? 443 : 80;
requestParameters.uri = parts.path;
requestParameters.uri = parts.path.length ? parts.path : "/";
}
~this() {

View File

@ -2118,6 +2118,10 @@ class LineEdit : Widget {
}
class TextEdit : Widget {
// FIXME
mixin ExperimentalTextComponent;
override int minHeight() { return Window.lineHeight; }
override int heightStretchiness() { return 3; }
override int widthStretchiness() { return 3; }
@ -2133,29 +2137,46 @@ class TextEdit : Widget {
this(Widget parent = null) {
super(parent);
textLayout = new TextLayout(Rectangle(0, 0, width, height));
this.paint = (ScreenPainter painter) {
painter.fillColor = Color.white;
painter.drawRectangle(Point(0, 0), width, height);
textLayout.boundingBox = Rectangle(4, 4, width - 8, height - 8);
painter.outlineColor = Color.black;
painter.drawText(Point(4, 4), content, Point(width - 4, height - 4));
// painter.drawText(Point(4, 4), content, Point(width - 4, height - 4));
textLayout.drawInto(painter);
};
caratTimer = new Timer(500, {
if(parentWindow.focusedWidget is this) {
if(!parentWindow.win.closed && parentWindow.focusedWidget is this) {
auto painter = this.draw();
painter.pen = Pen(Color.white, 1);
painter.rasterOp = RasterOp.xor;
painter.drawLine(Point(16, 0), Point(16, 16));
if(lastClick.element) {
painter.drawLine(
Point(lastClick.element.xOfIndex(lastClick.offset + 1), lastClick.element.boundingBox.top),
Point(lastClick.element.xOfIndex(lastClick.offset + 1), lastClick.element.boundingBox.bottom)
);
} else {
painter.drawLine(
Point(4, 4),
Point(4, 10)
);
}
}
});
defaultEventHandlers["click"] = delegate (Widget _this, Event ev) {
this.focus();
lastClick = textLayout.identify(ev.clientX, ev.clientY);
};
defaultEventHandlers["char"] = delegate (Widget _this, Event ev) {
content = content() ~ cast(char) ev.character;
textLayout.addText("" ~ cast(char) ev.character); // FIXME
redraw();
};
@ -2164,7 +2185,6 @@ class TextEdit : Widget {
//super();
}
string _content;
@property string content() {
version(win32_widgets) {
char[4096] buffer;
@ -2172,16 +2192,19 @@ class TextEdit : Widget {
// FIXME: GetWindowTextLength
auto l = GetWindowTextA(hwnd, buffer.ptr, buffer.length - 1);
if(l >= 0)
_content = buffer[0 .. l].idup;
return buffer[0 .. l].idup;
} else {
return textLayout.getPlainText();
}
return _content;
}
@property void content(string s) {
_content = s;
version(win32_widgets)
SetWindowTextA(hwnd, toStringzInternal(s));
else
else {
textLayout.clear();
textLayout.addText(s);
redraw();
}
}
void focus() {
@ -2193,6 +2216,8 @@ class TextEdit : Widget {
} else {
Timer caratTimer;
TextLayout textLayout;
TextIdentifyResult lastClick;
}
}

1
png.d
View File

@ -15,6 +15,7 @@ void writePng(string filename, MemoryImage mi) {
else if(auto p = cast(TrueColorImage) mi)
png = pngFromImage(p);
else assert(0);
import std.file;
std.file.write(filename, writePng(png));
}

View File

@ -805,6 +805,16 @@ class SimpleWindow : CapableOfHandlingNativeEvent {
hidden = true;
}
/// Hide cursor when it enters the window.
void hideCursor() {
if (!_closed) impl.hideCursor();
}
/// Don't hide cursor when it enters the window.
void showCursor() {
if (!_closed) impl.showCursor();
}
private bool _hidden;
/// Returns true if the window is hidden.
@ -3395,6 +3405,16 @@ version(Windows) {
// Mix this into the SimpleWindow class
mixin template NativeSimpleWindowImplementation() {
int curHidden = 0; // counter
void hideCursor () {
++curHidden;
}
void showCursor () {
--curHidden;
}
ScreenPainter getPainter() {
return ScreenPainter(this, hwnd);
}
@ -3538,6 +3558,11 @@ version(Windows) {
wind.handleMouseEvent(mouse);
}
// hide cursor in client area if necessary
if (curHidden > 0 && msg == WM_SETCURSOR && cast(ushort)lParam == HTCLIENT) {
SetCursor(null);
return 1;
}
switch(msg) {
case WM_CHAR:
@ -4430,6 +4455,8 @@ version(X11) {
Pixmap buffer;
XIC xic; // input context
int curHidden = 0; // counter
int blankCurPtr = 0;
void delegate(XEvent) setSelectionHandler;
void delegate(in char[]) getSelectionHandler;
@ -4441,6 +4468,23 @@ version(X11) {
return ScreenPainter(this, window);
}
void hideCursor () {
if (curHidden++ == 0) {
if (!blankCurPtr) {
static const(char)[1] cmbmp = 0;
XColor blackcolor = { 0, 0, 0, 0, 0, 0 };
Pixmap pm = XCreateBitmapFromData(display, window, cmbmp.ptr, 1, 1);
blankCurPtr = XCreatePixmapCursor(display, pm, pm, &blackcolor, &blackcolor, 0, 0);
XFreePixmap(display, pm);
}
XDefineCursor(display, window, blankCurPtr);
}
}
void showCursor () {
if (--curHidden == 0) XUndefineCursor(display, window);
}
void setTitle(string title) {
XTextProperty windowName;
windowName.value = title.ptr;
@ -4649,6 +4693,7 @@ version(X11) {
void closeWindow() {
if(buffer)
XFreePixmap(display, buffer);
if (blankCurPtr) XFreeCursor(display, blankCurPtr);
XDestroyWindow(display, window);
XFlush(display);
}
@ -5474,6 +5519,10 @@ Cursor XCreateFontCursor(Display*, uint shape);
int XDefineCursor(Display* display, Window w, Cursor cursor);
int XUndefineCursor(Display* display, Window w);
Pixmap XCreateBitmapFromData(Display* display, Drawable d, const(char)* data, uint width, uint height);
Cursor XCreatePixmapCursor(Display* display, Pixmap source, Pixmap mask, XColor* foreground_color, XColor* background_color, uint x, uint y);
int XFreeCursor(Display* display, Cursor cursor);
int XLookupString(XKeyEvent *event_struct, char *buffer_return, int bytes_buffer, KeySym *keysym_return, void *status_in_out);
int XwcLookupString(XIC ic, XKeyPressedEvent* event, wchar_t* buffer_return, int wchars_buffer, KeySym* keysym_return, Status* status_return);

View File

@ -57,6 +57,13 @@
+/
module terminal;
/*
Widgets:
tab widget
scrollback buffer
partitioned canvas
*/
// FIXME: ctrl+d eof on stdin
// FIXME: http://msdn.microsoft.com/en-us/library/windows/desktop/ms686016%28v=vs.85%29.aspx
@ -3321,6 +3328,79 @@ version(Windows) {
struct ScrollbackBuffer {
this(string name) {
this.name = name;
}
void write(T...)(T t) {
import std.conv : text;
addComponent(text(t), foreground_, background_, null);
}
void writeln(T...)(T t) {
write(t, "\n");
}
void writef(T...)(string fmt, T t) {
import std.format: format;
write(format(fmt, t));
}
void writefln(T...)(string fmt, T t) {
writef(fmt, t, "\n");
}
void clear() {
lines = null;
clickRegions = null;
scrollbackPosition = 0;
}
int foreground_ = Color.DEFAULT, background_ = Color.DEFAULT;
void color(int foreground, int background) {
this.foreground_ = foreground;
this.background_ = background;
}
void addComponent(string text, int foreground, int background, bool delegate() onclick) {
if(lines.length == 0) {
addLine();
}
bool first = true;
import std.algorithm;
foreach(t; splitter(text, "\n")) {
if(!first) addLine();
first = false;
lines[$-1].components ~= LineComponent(t, foreground, background, onclick);
}
}
void addLine() {
lines ~= Line();
if(scrollbackPosition) // if the user is scrolling back, we want to keep them basically centered where they are
scrollbackPosition++;
}
void addLine(string line) {
lines ~= Line([LineComponent(line)]);
if(scrollbackPosition) // if the user is scrolling back, we want to keep them basically centered where they are
scrollbackPosition++;
}
void scrollUp(int lines = 1) {
scrollbackPosition += lines;
//if(scrollbackPosition >= this.lines.length)
// scrollbackPosition = cast(int) this.lines.length - 1;
}
void scrollDown(int lines = 1) {
scrollbackPosition -= lines;
if(scrollbackPosition < 0)
scrollbackPosition = 0;
}
struct LineComponent {
string text;
int color = Color.DEFAULT;
@ -3495,9 +3575,11 @@ struct ScrollbackBuffer {
}
}
if(written < width)
foreach(i; written .. width)
terminal.write(" ");
if(written < width) {
terminal.color(Color.DEFAULT, Color.DEFAULT);
foreach(i; written .. width)
terminal.write(" ");
}
linePos++;
@ -3505,12 +3587,14 @@ struct ScrollbackBuffer {
break;
}
if(linePos < height)
foreach(i; linePos .. height) {
if(i >= 0 && i < height) {
terminal.moveTo(x, y + i);
foreach(w; 0 .. width)
terminal.write(" ");
if(linePos < height) {
terminal.color(Color.DEFAULT, Color.DEFAULT);
foreach(i; linePos .. height) {
if(i >= 0 && i < height) {
terminal.moveTo(x, y + i);
foreach(w; 0 .. width)
terminal.write(" ");
}
}
}
}
@ -3523,24 +3607,6 @@ struct ScrollbackBuffer {
}
private ClickRegion[] clickRegions;
void addLine(string line) {
lines ~= Line([LineComponent(line)]);
if(scrollbackPosition) // if the user is scrolling back, we want to keep them basically centered where they are
scrollbackPosition++;
}
void scrollUp(int lines = 1) {
scrollbackPosition += lines;
//if(scrollbackPosition >= this.lines.length)
// scrollbackPosition = cast(int) this.lines.length - 1;
}
void scrollDown(int lines = 1) {
scrollbackPosition -= lines;
if(scrollbackPosition < 0)
scrollbackPosition = 0;
}
/// Default event handling for this widget. Call this only after drawing it into a rectangle
/// and only if the event ought to be dispatched to it (which you determine however you want;
/// you could dispatch all events to it, or perhaps filter some out too)