mirror of https://github.com/adamdruppe/arsd.git
minigui combo boxes on linux
This commit is contained in:
parent
fb4b5bd81b
commit
45e4fc98ec
228
minigui.d
228
minigui.d
|
@ -42,6 +42,31 @@
|
||||||
+/
|
+/
|
||||||
module arsd.minigui;
|
module arsd.minigui;
|
||||||
|
|
||||||
|
public import arsd.simpledisplay;
|
||||||
|
|
||||||
|
version(Windows)
|
||||||
|
import core.sys.windows.windows;
|
||||||
|
|
||||||
|
// this is a hack to call the original window procedure on native win32 widgets if our event listener thing prevents default.
|
||||||
|
private bool lastDefaultPrevented;
|
||||||
|
|
||||||
|
version(Windows) {
|
||||||
|
// use native widgets when available unless specifically asked otherwise
|
||||||
|
version(custom_widgets) {
|
||||||
|
enum bool UsingCustomWidgets = true;
|
||||||
|
} else {
|
||||||
|
version = win32_widgets;
|
||||||
|
enum bool UsingCustomWidgets = false;
|
||||||
|
}
|
||||||
|
// and native theming when needed
|
||||||
|
//version = win32_theming;
|
||||||
|
} else {
|
||||||
|
enum bool UsingCustomWidgets = true;
|
||||||
|
version=custom_widgets;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
|
||||||
The main goals of minigui.d are to:
|
The main goals of minigui.d are to:
|
||||||
|
@ -125,6 +150,51 @@ abstract class ComboboxBase : Widget {
|
||||||
|
|
||||||
override int minHeight() { return Window.lineHeight * 4 / 3; }
|
override int minHeight() { return Window.lineHeight * 4 / 3; }
|
||||||
override int maxHeight() { return Window.lineHeight * 4 / 3; }
|
override int maxHeight() { return Window.lineHeight * 4 / 3; }
|
||||||
|
|
||||||
|
version(custom_widgets) {
|
||||||
|
SimpleWindow dropDown;
|
||||||
|
void popup() {
|
||||||
|
auto w = width;
|
||||||
|
auto h = this.options.length * Window.lineHeight + 8;
|
||||||
|
|
||||||
|
auto coord = this.globalCoordinates();
|
||||||
|
auto dropDown = new SimpleWindow(
|
||||||
|
w, h,
|
||||||
|
null, OpenGlOptions.no, Resizability.fixedSize, WindowTypes.dropdownMenu, WindowFlags.dontAutoShow/*, window*/);
|
||||||
|
|
||||||
|
dropDown.move(coord.x, coord.y + this.height);
|
||||||
|
|
||||||
|
{
|
||||||
|
auto painter = dropDown.draw();
|
||||||
|
draw3dFrame(0, 0, w, h, painter, FrameStyle.risen);
|
||||||
|
auto p = Point(4, 4);
|
||||||
|
painter.outlineColor = Color.black;
|
||||||
|
foreach(option; options) {
|
||||||
|
painter.drawText(p, option);
|
||||||
|
p.y += Window.lineHeight;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
dropDown.setEventHandlers(
|
||||||
|
(MouseEvent event) {
|
||||||
|
if(event.type == MouseEventType.buttonPressed) {
|
||||||
|
auto element = (event.y - 4) / Window.lineHeight;
|
||||||
|
if(element >= 0 && element <= options.length) {
|
||||||
|
selection = element;
|
||||||
|
|
||||||
|
auto t = new Event("changed", this);
|
||||||
|
t.dispatch();
|
||||||
|
}
|
||||||
|
dropDown.close();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
);
|
||||||
|
|
||||||
|
dropDown.show();
|
||||||
|
dropDown.grabInput();
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/++
|
/++
|
||||||
|
@ -135,9 +205,19 @@ class DropDownSelection : ComboboxBase {
|
||||||
this(Widget parent = null) {
|
this(Widget parent = null) {
|
||||||
version(win32_widgets)
|
version(win32_widgets)
|
||||||
super(3 /* CBS_DROPDOWNLIST */, parent);
|
super(3 /* CBS_DROPDOWNLIST */, parent);
|
||||||
else version(custom_widgets)
|
else version(custom_widgets) {
|
||||||
super(parent);
|
super(parent);
|
||||||
else static assert(false);
|
paint = delegate(ScreenPainter painter) {
|
||||||
|
draw3dFrame(this, painter, FrameStyle.risen);
|
||||||
|
painter.outlineColor = Color.black;
|
||||||
|
painter.drawText(Point(4, 4), selection == -1 ? "" : options[selection]);
|
||||||
|
painter.drawLine(Point(width - 4 - 8, 4), Point(width - 4 - 2, height - 2));
|
||||||
|
painter.drawLine(Point(width - 2, 4), Point(width - 4 - 2, height - 2));
|
||||||
|
};
|
||||||
|
|
||||||
|
addEventListener("changed", &this.redraw);
|
||||||
|
addEventListener("click", &this.popup);
|
||||||
|
} else static assert(false);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -149,10 +229,32 @@ class FreeEntrySelection : ComboboxBase {
|
||||||
this(Widget parent = null) {
|
this(Widget parent = null) {
|
||||||
version(win32_widgets)
|
version(win32_widgets)
|
||||||
super(2 /* CBS_DROPDOWN */, parent);
|
super(2 /* CBS_DROPDOWN */, parent);
|
||||||
else version(custom_widgets)
|
else version(custom_widgets) {
|
||||||
super(parent);
|
super(parent);
|
||||||
|
auto hl = new HorizontalLayout(this);
|
||||||
|
lineEdit = new LineEdit(hl);
|
||||||
|
lineEdit.content = selection == -1 ? "" : options[selection];
|
||||||
|
|
||||||
|
auto btn = new class Button {
|
||||||
|
this() {
|
||||||
|
super("V", hl);
|
||||||
|
}
|
||||||
|
override int maxWidth() {
|
||||||
|
return 16;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
btn.addEventListener("triggered", &this.popup);
|
||||||
|
addEventListener("changed", {
|
||||||
|
lineEdit.content = selection == -1 ? "" : options[selection];
|
||||||
|
redraw();
|
||||||
|
});
|
||||||
|
}
|
||||||
else static assert(false);
|
else static assert(false);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
version(custom_widgets) {
|
||||||
|
LineEdit lineEdit;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/++
|
/++
|
||||||
|
@ -162,14 +264,91 @@ class ComboBox : ComboboxBase {
|
||||||
this(Widget parent = null) {
|
this(Widget parent = null) {
|
||||||
version(win32_widgets)
|
version(win32_widgets)
|
||||||
super(1 /* CBS_SIMPLE */, parent);
|
super(1 /* CBS_SIMPLE */, parent);
|
||||||
else version(custom_widgets)
|
else version(custom_widgets) {
|
||||||
super(parent);
|
super(parent);
|
||||||
else static assert(false);
|
lineEdit = new LineEdit(this);
|
||||||
|
listWidget = new ListWidget(this);
|
||||||
|
listWidget.multiSelect = false;
|
||||||
|
listWidget.addEventListener("change", delegate(Widget, Event) {
|
||||||
|
string c = null;
|
||||||
|
foreach(option; listWidget.options)
|
||||||
|
if(option.selected) {
|
||||||
|
c = option.label;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
lineEdit.content = c;
|
||||||
|
});
|
||||||
|
} else static assert(false);
|
||||||
}
|
}
|
||||||
|
|
||||||
override int minHeight() { return Window.lineHeight * 3; }
|
override int minHeight() { return Window.lineHeight * 3; }
|
||||||
override int maxHeight() { return int.max; }
|
override int maxHeight() { return int.max; }
|
||||||
override int heightStretchiness() { return 2; }
|
override int heightStretchiness() { return 2; }
|
||||||
|
|
||||||
|
version(custom_widgets) {
|
||||||
|
LineEdit lineEdit;
|
||||||
|
ListWidget listWidget;
|
||||||
|
|
||||||
|
override void addOption(string s) {
|
||||||
|
listWidget.options ~= ListWidget.Option(s);
|
||||||
|
ComboboxBase.addOption(s);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/++
|
||||||
|
|
||||||
|
+/
|
||||||
|
version(custom_widgets)
|
||||||
|
class ListWidget : Widget {
|
||||||
|
|
||||||
|
static struct Option {
|
||||||
|
string label;
|
||||||
|
bool selected;
|
||||||
|
}
|
||||||
|
|
||||||
|
this(Widget parent = null) {
|
||||||
|
super(parent);
|
||||||
|
|
||||||
|
defaultEventHandlers["click"] = delegate(Widget _this, Event event) {
|
||||||
|
auto y = (event.clientY - 4) / Window.lineHeight;
|
||||||
|
if(y >= 0 && y < options.length) {
|
||||||
|
if(!multiSelect)
|
||||||
|
foreach(ref opt; options)
|
||||||
|
opt.selected = false;
|
||||||
|
options[y].selected = !options[y].selected;
|
||||||
|
|
||||||
|
auto evt = new Event("change", this);
|
||||||
|
evt.dispatch();
|
||||||
|
|
||||||
|
redraw();
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
paint = delegate(ScreenPainter painter) {
|
||||||
|
draw3dFrame(this, painter, FrameStyle.sunk, Color.white);
|
||||||
|
|
||||||
|
auto pos = Point(4, 4);
|
||||||
|
foreach(idx, option; options) {
|
||||||
|
painter.fillColor = Color.white;
|
||||||
|
painter.outlineColor = Color.white;
|
||||||
|
painter.drawRectangle(pos, width - 8, Window.lineHeight);
|
||||||
|
painter.outlineColor = Color.black;
|
||||||
|
painter.drawText(pos, option.label);
|
||||||
|
if(option.selected) {
|
||||||
|
painter.rasterOp = RasterOp.xor;
|
||||||
|
painter.outlineColor = Color.white;
|
||||||
|
painter.fillColor = Color(255, 255, 0);
|
||||||
|
painter.drawRectangle(pos, width - 8, Window.lineHeight);
|
||||||
|
painter.rasterOp = RasterOp.normal;
|
||||||
|
}
|
||||||
|
pos.y += Window.lineHeight;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
Option[] options;
|
||||||
|
bool multiSelect;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -216,30 +395,6 @@ class DataView : Widget {
|
||||||
// http://svn.dsource.org/projects/bindings/trunk/win32/commctrl.d
|
// http://svn.dsource.org/projects/bindings/trunk/win32/commctrl.d
|
||||||
|
|
||||||
// FIXME: menus should prolly capture the mouse. ugh i kno.
|
// FIXME: menus should prolly capture the mouse. ugh i kno.
|
||||||
|
|
||||||
public import arsd.simpledisplay;
|
|
||||||
|
|
||||||
version(Windows)
|
|
||||||
import core.sys.windows.windows;
|
|
||||||
|
|
||||||
// this is a hack to call the original window procedure on native win32 widgets if our event listener thing prevents default.
|
|
||||||
private bool lastDefaultPrevented;
|
|
||||||
|
|
||||||
version(Windows) {
|
|
||||||
// use native widgets when available unless specifically asked otherwise
|
|
||||||
version(custom_widgets) {
|
|
||||||
enum bool UsingCustomWidgets = true;
|
|
||||||
} else {
|
|
||||||
version = win32_widgets;
|
|
||||||
enum bool UsingCustomWidgets = false;
|
|
||||||
}
|
|
||||||
// and native theming when needed
|
|
||||||
//version = win32_theming;
|
|
||||||
} else {
|
|
||||||
enum bool UsingCustomWidgets = true;
|
|
||||||
version=custom_widgets;
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
TextEdit needs:
|
TextEdit needs:
|
||||||
|
|
||||||
|
@ -1224,6 +1379,16 @@ class Window : Widget {
|
||||||
auto eleR = widgetAtPoint(this, ev.x, ev.y);
|
auto eleR = widgetAtPoint(this, ev.x, ev.y);
|
||||||
auto ele = eleR.widget;
|
auto ele = eleR.widget;
|
||||||
|
|
||||||
|
// a hack to get it relative to the widget.
|
||||||
|
eleR.x = ev.x;
|
||||||
|
eleR.y = ev.y;
|
||||||
|
auto pain = ele;
|
||||||
|
while(pain) {
|
||||||
|
eleR.x -= pain.x;
|
||||||
|
eleR.y -= pain.y;
|
||||||
|
pain = pain.parent;
|
||||||
|
}
|
||||||
|
|
||||||
if(mouseCapturedBy !is null) {
|
if(mouseCapturedBy !is null) {
|
||||||
if(ele !is mouseCapturedBy && !mouseCapturedBy.isAParentOf(ele))
|
if(ele !is mouseCapturedBy && !mouseCapturedBy.isAParentOf(ele))
|
||||||
ele = this;
|
ele = this;
|
||||||
|
@ -2396,9 +2561,11 @@ abstract class EditableTextWidget : Widget {
|
||||||
else version(custom_widgets) {
|
else version(custom_widgets) {
|
||||||
textLayout.clear();
|
textLayout.clear();
|
||||||
textLayout.addText(s);
|
textLayout.addText(s);
|
||||||
|
/*
|
||||||
textLayout.addText(ForegroundColor.red, s);
|
textLayout.addText(ForegroundColor.red, s);
|
||||||
textLayout.addText(ForegroundColor.blue, TextFormat.underline, "http://dpldocs.info/");
|
textLayout.addText(ForegroundColor.blue, TextFormat.underline, "http://dpldocs.info/");
|
||||||
textLayout.addText(" is the best!");
|
textLayout.addText(" is the best!");
|
||||||
|
*/
|
||||||
redraw();
|
redraw();
|
||||||
}
|
}
|
||||||
else static assert(false);
|
else static assert(false);
|
||||||
|
@ -2805,7 +2972,8 @@ WidgetAtPointResponse widgetAtPoint(Widget starting, int x, int y) {
|
||||||
starting = child;
|
starting = child;
|
||||||
x -= child.x;
|
x -= child.x;
|
||||||
y -= child.y;
|
y -= child.y;
|
||||||
child = starting.widgetAtPoint(x, y).widget;//starting.getChildAtPosition(x, y);
|
auto r = starting.widgetAtPoint(x, y);//starting.getChildAtPosition(x, y);
|
||||||
|
child = r.widget;
|
||||||
if(child is starting)
|
if(child is starting)
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue