mirror of https://github.com/adamdruppe/arsd.git
more stuff
This commit is contained in:
parent
a2fbd27b66
commit
e1de7a72d5
381
minigui.d
381
minigui.d
|
@ -1,47 +1,66 @@
|
||||||
module arsd.minigui;
|
module arsd.minigui;
|
||||||
|
|
||||||
|
// http://msdn.microsoft.com/en-us/library/windows/desktop/bb775491(v=vs.85).aspx#PROGRESS_CLASS
|
||||||
|
|
||||||
import simpledisplay;
|
import simpledisplay;
|
||||||
|
|
||||||
version(Windows) {
|
version(Windows) {
|
||||||
// use native widgets when available
|
// use native widgets when available unless specifically asked otherwise
|
||||||
|
version(custom_widgets) {}
|
||||||
|
else {
|
||||||
version = win32_widgets;
|
version = win32_widgets;
|
||||||
|
}
|
||||||
// and native theming when needed
|
// and native theming when needed
|
||||||
version = win32_theming;
|
version = win32_theming;
|
||||||
}
|
}
|
||||||
|
|
||||||
enum windowBackgroundColor = Color(190, 190, 190);
|
enum windowBackgroundColor = Color(190, 190, 190);
|
||||||
|
|
||||||
private const(char)* toStringz(string s) { return (s ~ '\0').ptr; }
|
private const(char)* toStringzInternal(string s) { return (s ~ '\0').ptr; }
|
||||||
|
|
||||||
/*
|
|
||||||
class Action {
|
class Action {
|
||||||
|
version(win32_widgets) {
|
||||||
|
int id;
|
||||||
|
static int lastId = 9000;
|
||||||
|
static Action[int] mapping;
|
||||||
|
}
|
||||||
|
|
||||||
|
this(string label, ushort icon = 0) {
|
||||||
|
this.label = label;
|
||||||
|
this.iconId = icon;
|
||||||
|
version(win32_widgets) {
|
||||||
|
id = ++lastId;
|
||||||
|
mapping[id] = this;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
string label;
|
string label;
|
||||||
|
ushort iconId;
|
||||||
// icon
|
// icon
|
||||||
|
|
||||||
// when it is triggered, the triggered event is fired on the window
|
// when it is triggered, the triggered event is fired on the window
|
||||||
void delegate()[] triggered;
|
void delegate()[] triggered;
|
||||||
}
|
}
|
||||||
*/
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
plan:
|
plan:
|
||||||
keyboard accelerators
|
keyboard accelerators
|
||||||
|
|
||||||
menus (and popups and tooltips)
|
* menus (and popups and tooltips)
|
||||||
status bar
|
* status bar
|
||||||
toolbars and buttons
|
* toolbars and buttons
|
||||||
|
|
||||||
sortable table view
|
sortable table view
|
||||||
|
|
||||||
maybe notification area icons
|
maybe notification area icons
|
||||||
|
|
||||||
radio box
|
* radio box
|
||||||
toggle buttons (optionally mutually exclusive, like in Paint)
|
toggle buttons (optionally mutually exclusive, like in Paint)
|
||||||
label, rich text display, multi line plain text (selectable)
|
label, rich text display, multi line plain text (selectable)
|
||||||
fieldset
|
fieldset
|
||||||
nestable grid layout
|
* nestable grid layout
|
||||||
single line text input
|
single line text input
|
||||||
multi line text input
|
* multi line text input
|
||||||
slider
|
slider
|
||||||
spinner
|
spinner
|
||||||
list box
|
list box
|
||||||
|
@ -99,6 +118,9 @@ mixin template LayoutInfo() {
|
||||||
int maxHeight() { return int.max; }
|
int maxHeight() { return int.max; }
|
||||||
int widthStretchiness() { return 1; }
|
int widthStretchiness() { return 1; }
|
||||||
int heightStretchiness() { return 1; }
|
int heightStretchiness() { return 1; }
|
||||||
|
|
||||||
|
int margin() { return 0; }
|
||||||
|
int padding() { return 0; }
|
||||||
//LinePreference linePreference() { return LinePreference.PreferOwnLine; }
|
//LinePreference linePreference() { return LinePreference.PreferOwnLine; }
|
||||||
|
|
||||||
void recomputeChildLayout() {
|
void recomputeChildLayout() {
|
||||||
|
@ -114,16 +136,20 @@ void recomputeChildLayout(string relevantMeasure)(Widget parent) {
|
||||||
if(parent.children.length == 0)
|
if(parent.children.length == 0)
|
||||||
return;
|
return;
|
||||||
// my own width and height should already be set by the caller of this function...
|
// my own width and height should already be set by the caller of this function...
|
||||||
int spaceRemaining = mixin("parent." ~ relevantMeasure);
|
int spaceRemaining = mixin("parent." ~ relevantMeasure) - parent.padding() * 2;
|
||||||
int stretchinessSum;
|
int stretchinessSum;
|
||||||
foreach(child; parent.children) {
|
foreach(child; parent.children) {
|
||||||
static if(calcingV) {
|
static if(calcingV) {
|
||||||
child.width = parent.width; // block element style
|
child.width = parent.width - child.margin() * 2 - parent.padding() * 2; // block element style
|
||||||
|
if(child.width < 0)
|
||||||
|
child.width = 0;
|
||||||
if(child.width > child.maxWidth())
|
if(child.width > child.maxWidth())
|
||||||
child.width = child.maxWidth();
|
child.width = child.maxWidth();
|
||||||
child.height = child.minHeight();
|
child.height = child.minHeight();
|
||||||
} else {
|
} else {
|
||||||
child.height = parent.height; // block element style
|
if(child.height < 0)
|
||||||
|
child.height = 0;
|
||||||
|
child.height = parent.height - child.margin() * 2 - parent.padding() * 2;
|
||||||
if(child.height > child.maxHeight())
|
if(child.height > child.maxHeight())
|
||||||
child.height = child.maxHeight();
|
child.height = child.maxHeight();
|
||||||
child.width = child.minWidth();
|
child.width = child.minWidth();
|
||||||
|
@ -160,20 +186,24 @@ void recomputeChildLayout(string relevantMeasure)(Widget parent) {
|
||||||
} else if(mixin("child." ~ relevantMeasure) < maximum) {
|
} else if(mixin("child." ~ relevantMeasure) < maximum) {
|
||||||
stretchinessSum += mixin("child." ~ relevantMeasure ~ "Stretchiness()");
|
stretchinessSum += mixin("child." ~ relevantMeasure ~ "Stretchiness()");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
spaceRemaining -= child.margin();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
int currentPos = 0;
|
int currentPos = parent.padding();
|
||||||
foreach(child; parent.children) {
|
foreach(child; parent.children) {
|
||||||
|
currentPos += child.margin();
|
||||||
static if(calcingV) {
|
static if(calcingV) {
|
||||||
child.x = 0;
|
child.x = parent.padding() + child.margin();
|
||||||
child.y = currentPos;
|
child.y = currentPos;
|
||||||
} else {
|
} else {
|
||||||
child.x = currentPos;
|
child.x = currentPos;
|
||||||
child.y = 0;
|
child.y = parent.padding() + child.margin();
|
||||||
|
|
||||||
}
|
}
|
||||||
currentPos += mixin("child." ~ relevantMeasure);
|
currentPos += mixin("child." ~ relevantMeasure);
|
||||||
|
currentPos += child.margin();
|
||||||
|
|
||||||
child.recomputeChildLayout();
|
child.recomputeChildLayout();
|
||||||
}
|
}
|
||||||
|
@ -196,7 +226,6 @@ mixin template StyleInfo(string windowType) {
|
||||||
// OK so we need to make getting at the native window stuff possible in simpledisplay.d
|
// OK so we need to make getting at the native window stuff possible in simpledisplay.d
|
||||||
// and here, it must be integratable with the layout, the event system, and not be painted over.
|
// and here, it must be integratable with the layout, the event system, and not be painted over.
|
||||||
version(win32_widgets) {
|
version(win32_widgets) {
|
||||||
import std.c.windows.windows;
|
|
||||||
extern(Windows)
|
extern(Windows)
|
||||||
int HookedWndProc(HWND hWnd, UINT iMessage, WPARAM wParam, LPARAM lParam) nothrow {
|
int HookedWndProc(HWND hWnd, UINT iMessage, WPARAM wParam, LPARAM lParam) nothrow {
|
||||||
if(auto te = hWnd in Widget.nativeMapping) {
|
if(auto te = hWnd in Widget.nativeMapping) {
|
||||||
|
@ -214,10 +243,16 @@ version(win32_widgets) {
|
||||||
assert(p.parentWindow !is null);
|
assert(p.parentWindow !is null);
|
||||||
assert(p.parentWindow.win.impl.hwnd !is null);
|
assert(p.parentWindow.win.impl.hwnd !is null);
|
||||||
|
|
||||||
|
HWND phwnd;
|
||||||
|
if(p.parent !is null && p.parent.hwnd !is null)
|
||||||
|
phwnd = p.parent.hwnd;
|
||||||
|
else
|
||||||
|
phwnd = p.parentWindow.win.impl.hwnd;
|
||||||
|
|
||||||
style |= WS_VISIBLE | WS_CHILD;
|
style |= WS_VISIBLE | WS_CHILD;
|
||||||
p.hwnd = CreateWindow(toStringz(className), toStringz(windowText), style,
|
p.hwnd = CreateWindow(toStringzInternal(className), toStringzInternal(windowText), style,
|
||||||
CW_USEDEFAULT, CW_USEDEFAULT, 100, 100,
|
CW_USEDEFAULT, CW_USEDEFAULT, 100, 100,
|
||||||
p.parentWindow.win.impl.hwnd, null, cast(HINSTANCE) GetModuleHandle(null), null);
|
phwnd, null, cast(HINSTANCE) GetModuleHandle(null), null);
|
||||||
|
|
||||||
assert(p.hwnd !is null);
|
assert(p.hwnd !is null);
|
||||||
|
|
||||||
|
@ -267,7 +302,7 @@ class Widget {
|
||||||
void registerMovement() {
|
void registerMovement() {
|
||||||
version(win32_widgets) {
|
version(win32_widgets) {
|
||||||
if(hwnd) {
|
if(hwnd) {
|
||||||
auto pos = getChildPositionRelativeToParentOrigin(this);
|
auto pos = getChildPositionRelativeToParentHwnd(this);
|
||||||
MoveWindow(hwnd, pos[0], pos[1], width, height, true);
|
MoveWindow(hwnd, pos[0], pos[1], width, height, true);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -459,6 +494,16 @@ class Window : Widget {
|
||||||
win.close();
|
win.close();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
override bool dispatchKeyEvent(KeyEvent ev) {
|
||||||
|
if(focusedWidget) {
|
||||||
|
auto event = new Event(ev.pressed ? "keydown" : "keyup", focusedWidget);
|
||||||
|
event.character = ev.character;
|
||||||
|
event.key = ev.key;
|
||||||
|
event.dispatch();
|
||||||
|
}
|
||||||
|
return super.dispatchKeyEvent(ev);
|
||||||
|
}
|
||||||
|
|
||||||
override bool dispatchCharEvent(dchar ch) {
|
override bool dispatchCharEvent(dchar ch) {
|
||||||
if(focusedWidget) {
|
if(focusedWidget) {
|
||||||
auto event = new Event("char", focusedWidget);
|
auto event = new Event("char", focusedWidget);
|
||||||
|
@ -488,10 +533,14 @@ class Window : Widget {
|
||||||
event.clientY = ev.y;
|
event.clientY = ev.y;
|
||||||
event.dispatch();
|
event.dispatch();
|
||||||
}
|
}
|
||||||
} else if(ev.type == 0 && mouseLastOver !is ele) {
|
} else if(ev.type == 0) {
|
||||||
// motion
|
// motion
|
||||||
Event event;
|
Event event = new Event("mousemove", ele);
|
||||||
|
event.clientX = ev.x;
|
||||||
|
event.clientY = ev.y;
|
||||||
|
event.dispatch();
|
||||||
|
|
||||||
|
if(mouseLastOver !is ele) {
|
||||||
if(ele !is null) {
|
if(ele !is null) {
|
||||||
if(!isAParentOf(ele, mouseLastOver)) {
|
if(!isAParentOf(ele, mouseLastOver)) {
|
||||||
event = new Event("mouseenter", ele);
|
event = new Event("mouseenter", ele);
|
||||||
|
@ -522,6 +571,7 @@ class Window : Widget {
|
||||||
|
|
||||||
mouseLastOver = ele;
|
mouseLastOver = ele;
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
return super.dispatchMouseEvent(ev);
|
return super.dispatchMouseEvent(ev);
|
||||||
}
|
}
|
||||||
|
@ -548,7 +598,7 @@ class MainWindow : Window {
|
||||||
if(this.statusBar !is null && event.target.statusTip.length)
|
if(this.statusBar !is null && event.target.statusTip.length)
|
||||||
this.statusBar.content = event.target.statusTip;
|
this.statusBar.content = event.target.statusTip;
|
||||||
else if(this.statusBar !is null && _this.statusTip.length)
|
else if(this.statusBar !is null && _this.statusTip.length)
|
||||||
this.statusBar.content = _this.statusTip;
|
this.statusBar.content = _this.statusTip ~ " " ~ event.target.toString();
|
||||||
};
|
};
|
||||||
|
|
||||||
version(win32_widgets)
|
version(win32_widgets)
|
||||||
|
@ -562,10 +612,14 @@ class MainWindow : Window {
|
||||||
// case BN_CLICKED: aka 0
|
// case BN_CLICKED: aka 0
|
||||||
case 1:
|
case 1:
|
||||||
auto idm = LOWORD(wParam);
|
auto idm = LOWORD(wParam);
|
||||||
if(auto item = idm in menuCommandMapping) {
|
if(auto item = idm in Action.mapping) {
|
||||||
|
foreach(handler; (*item).triggered)
|
||||||
|
handler();
|
||||||
|
/*
|
||||||
auto event = new Event("triggered", *item);
|
auto event = new Event("triggered", *item);
|
||||||
event.button = idm;
|
event.button = idm;
|
||||||
event.dispatch();
|
event.dispatch();
|
||||||
|
*/
|
||||||
} else {
|
} else {
|
||||||
auto buttonHandle = cast(HWND) lParam;
|
auto buttonHandle = cast(HWND) lParam;
|
||||||
if(auto widget = buttonHandle in Widget.nativeMapping) {
|
if(auto widget = buttonHandle in Widget.nativeMapping) {
|
||||||
|
@ -598,10 +652,6 @@ class MainWindow : Window {
|
||||||
clientArea.addChild(c, position);
|
clientArea.addChild(c, position);
|
||||||
}
|
}
|
||||||
|
|
||||||
version(win32_widgets)
|
|
||||||
static MenuItem[int] menuCommandMapping;
|
|
||||||
static int lastId = 9000;
|
|
||||||
|
|
||||||
MenuBar _menu;
|
MenuBar _menu;
|
||||||
MenuBar menu() { return _menu; }
|
MenuBar menu() { return _menu; }
|
||||||
void menu(MenuBar m) {
|
void menu(MenuBar m) {
|
||||||
|
@ -643,39 +693,36 @@ class MainWindow : Window {
|
||||||
class ToolBar : Widget {
|
class ToolBar : Widget {
|
||||||
override int maxHeight() { return 40; }
|
override int maxHeight() { return 40; }
|
||||||
|
|
||||||
version(win32_widgets) {
|
version(win32_widgets)
|
||||||
HIMAGELIST imageList;
|
HIMAGELIST imageList;
|
||||||
this(Widget parent = null) {
|
|
||||||
|
this(Action[] actions, Widget parent = null) {
|
||||||
super(parent);
|
super(parent);
|
||||||
|
|
||||||
|
version(win32_widgets) {
|
||||||
parentWindow = parent.parentWindow;
|
parentWindow = parent.parentWindow;
|
||||||
createWin32Window(this, "ToolbarWindow32", "", 0);
|
createWin32Window(this, "ToolbarWindow32", "", 0);
|
||||||
|
|
||||||
auto numberOfButtons = 3;
|
|
||||||
|
|
||||||
imageList = ImageList_Create(
|
imageList = ImageList_Create(
|
||||||
// width, height
|
// width, height
|
||||||
16, 16,
|
16, 16,
|
||||||
ILC_COLOR16 | ILC_MASK,
|
ILC_COLOR16 | ILC_MASK,
|
||||||
numberOfButtons, 0);
|
16 /*numberOfButtons*/, 0);
|
||||||
|
|
||||||
SendMessageA(hwnd, TB_SETIMAGELIST, cast(WPARAM) 0, cast(LPARAM) imageList);
|
SendMessageA(hwnd, TB_SETIMAGELIST, cast(WPARAM) 0, cast(LPARAM) imageList);
|
||||||
SendMessageA(hwnd, TB_LOADIMAGES, cast(WPARAM) IDB_STD_SMALL_COLOR, cast(LPARAM) HINST_COMMCTRL);
|
SendMessageA(hwnd, TB_LOADIMAGES, cast(WPARAM) IDB_STD_SMALL_COLOR, cast(LPARAM) HINST_COMMCTRL);
|
||||||
|
|
||||||
TBBUTTON[] buttons;
|
TBBUTTON[] buttons;
|
||||||
buttons ~= TBBUTTON(MAKELONG(STD_FILENEW, 0), 9435, TBSTATE_ENABLED, 0, 0, 0, cast(int) "New".ptr);
|
|
||||||
buttons ~= TBBUTTON(MAKELONG(STD_FILEOPEN, 0), 9435, TBSTATE_ENABLED, 0, 0, 0, cast(int) "Open".ptr);
|
// FIXME: I_IMAGENONE is if here is no icon
|
||||||
buttons ~= TBBUTTON(MAKELONG(STD_FILESAVE, 0), 9435, TBSTATE_ENABLED, 0, 0, 0, cast(int) "Save".ptr);
|
foreach(action; actions)
|
||||||
|
buttons ~= TBBUTTON(MAKELONG(action.iconId, 0), action.id, TBSTATE_ENABLED, 0, 0, 0, cast(int) toStringzInternal(action.label));
|
||||||
|
|
||||||
SendMessageA(hwnd, TB_BUTTONSTRUCTSIZE, cast(WPARAM)TBBUTTON.sizeof, 0);
|
SendMessageA(hwnd, TB_BUTTONSTRUCTSIZE, cast(WPARAM)TBBUTTON.sizeof, 0);
|
||||||
SendMessageA(hwnd, TB_ADDBUTTONSA, cast(WPARAM)numberOfButtons, cast(LPARAM)buttons.ptr);
|
SendMessageA(hwnd, TB_ADDBUTTONSA, cast(WPARAM) buttons.length, cast(LPARAM)buttons.ptr);
|
||||||
|
|
||||||
}
|
|
||||||
} else {
|
} else {
|
||||||
this(Widget parent = null) {
|
foreach(action; actions)
|
||||||
super(parent);
|
addChild(new ToolButton(action));
|
||||||
addChild(new ToolButton("New"));
|
|
||||||
addChild(new ToolButton("Open"));
|
|
||||||
addChild(new ToolButton("Save"));
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -688,6 +735,28 @@ class ToolButton : Button {
|
||||||
this(string label, Widget parent = null) {
|
this(string label, Widget parent = null) {
|
||||||
super(label, parent);
|
super(label, parent);
|
||||||
}
|
}
|
||||||
|
this(Action action, Widget parent = null) {
|
||||||
|
super(action.label, parent);
|
||||||
|
this.action = action;
|
||||||
|
|
||||||
|
version(win32_widgets) {} else {
|
||||||
|
defaultEventHandlers["click"] = (Widget _this, Event event) {
|
||||||
|
foreach(handler; action.triggered)
|
||||||
|
handler();
|
||||||
|
};
|
||||||
|
|
||||||
|
paint = (ScreenPainter painter) {
|
||||||
|
painter.outlineColor = Color.black;
|
||||||
|
if(isHovering) {
|
||||||
|
painter.fillColor = Color.transparent;
|
||||||
|
painter.drawRectangle(Point(0, 0), width, height);
|
||||||
|
}
|
||||||
|
painter.drawText(Point(0, 0), action.label, Point(width, height), TextAlignment.Center | TextAlignment.VerticalCenter);
|
||||||
|
};
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
Action action;
|
||||||
|
|
||||||
override int maxWidth() { return 40; }
|
override int maxWidth() { return 40; }
|
||||||
override int minWidth() { return 40; }
|
override int minWidth() { return 40; }
|
||||||
|
@ -719,8 +788,7 @@ class MenuBar : Widget {
|
||||||
this.addChild(item);
|
this.addChild(item);
|
||||||
items ~= item;
|
items ~= item;
|
||||||
version(win32_widgets) {
|
version(win32_widgets) {
|
||||||
MainWindow.menuCommandMapping[MainWindow.lastId + 1] = item;
|
AppendMenu(handle, MF_STRING, item.action is null ? 9000 : item.action.id, toStringzInternal(item.label));
|
||||||
AppendMenu(handle, MF_STRING, ++MainWindow.lastId, toStringz(item.label));
|
|
||||||
}
|
}
|
||||||
return item;
|
return item;
|
||||||
}
|
}
|
||||||
|
@ -732,7 +800,7 @@ class MenuBar : Widget {
|
||||||
items ~= mbItem;
|
items ~= mbItem;
|
||||||
|
|
||||||
version(win32_widgets) {
|
version(win32_widgets) {
|
||||||
AppendMenu(handle, MF_STRING | MF_POPUP, cast(UINT) item.handle, toStringz(item.label));
|
AppendMenu(handle, MF_STRING | MF_POPUP, cast(UINT) item.handle, toStringzInternal(item.label));
|
||||||
} else {
|
} else {
|
||||||
mbItem.defaultEventHandlers["click"] = (Widget e, Event ev) {
|
mbItem.defaultEventHandlers["click"] = (Widget e, Event ev) {
|
||||||
item.parentWindow = e.parentWindow;
|
item.parentWindow = e.parentWindow;
|
||||||
|
@ -780,7 +848,9 @@ class StatusBar : Widget {
|
||||||
WPARAM wParam;
|
WPARAM wParam;
|
||||||
auto idx = 0; // see also SB_SIMPLEID
|
auto idx = 0; // see also SB_SIMPLEID
|
||||||
wParam = idx;
|
wParam = idx;
|
||||||
SendMessageA(hwnd, SB_SETTEXT, wParam, cast(LPARAM) toStringz(s));
|
SendMessageA(hwnd, SB_SETTEXT, wParam, cast(LPARAM) toStringzInternal(s));
|
||||||
|
|
||||||
|
SendMessageA(hwnd, WM_USER + 4 /*SB_SETPARTS*/, 5, cast(int) [32, 100, 200, 400, -1].ptr);
|
||||||
} else {
|
} else {
|
||||||
_content = s;
|
_content = s;
|
||||||
redraw();
|
redraw();
|
||||||
|
@ -807,7 +877,122 @@ class StatusBar : Widget {
|
||||||
|
|
||||||
override int maxHeight() { return Window.lineHeight; }
|
override int maxHeight() { return Window.lineHeight; }
|
||||||
override int minHeight() { return Window.lineHeight; }
|
override int minHeight() { return Window.lineHeight; }
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Displays an in-progress indicator without known values
|
||||||
|
version(none)
|
||||||
|
class IndefiniteProgressBar : Widget {
|
||||||
|
version(win32_widgets)
|
||||||
|
this(Widget parent = null) {
|
||||||
|
super(parent);
|
||||||
|
parentWindow = parent.parentWindow;
|
||||||
|
createWin32Window(this, "msctls_progress32", "", 8 /* PBS_MARQUEE */);
|
||||||
|
}
|
||||||
|
override int minHeight() { return 10; }
|
||||||
|
}
|
||||||
|
|
||||||
|
/// A progress bar with a known endpoint and completion amount
|
||||||
|
class ProgressBar : Widget {
|
||||||
|
version(win32_widgets)
|
||||||
|
this(Widget parent = null) {
|
||||||
|
super(parent);
|
||||||
|
parentWindow = parent.parentWindow;
|
||||||
|
createWin32Window(this, "msctls_progress32", "", 0);
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
this(Widget parent = null) {
|
||||||
|
super(parent);
|
||||||
|
max = 100;
|
||||||
|
step = 10;
|
||||||
|
paint = (ScreenPainter painter) {
|
||||||
|
painter.fillColor = windowBackgroundColor;
|
||||||
|
painter.drawRectangle(Point(0, 0), width, height);
|
||||||
|
painter.fillColor = Color.blue;
|
||||||
|
painter.drawRectangle(Point(0, 0), width * current / max, height);
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
int current;
|
||||||
|
int max;
|
||||||
|
int step;
|
||||||
|
}
|
||||||
|
|
||||||
|
void advanceOneStep() {
|
||||||
|
version(win32_widgets)
|
||||||
|
SendMessageA(hwnd, PBM_STEPIT, 0, 0);
|
||||||
|
else
|
||||||
|
addToPosition(step);
|
||||||
|
}
|
||||||
|
|
||||||
|
void setStepIncrement(int increment) {
|
||||||
|
version(win32_widgets)
|
||||||
|
SendMessageA(hwnd, PBM_SETSTEP, increment, 0);
|
||||||
|
else
|
||||||
|
step = increment;
|
||||||
|
}
|
||||||
|
|
||||||
|
void addToPosition(int amount) {
|
||||||
|
version(win32_widgets)
|
||||||
|
SendMessageA(hwnd, PBM_DELTAPOS, amount, 0);
|
||||||
|
else {
|
||||||
|
setPosition(current + amount);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void setPosition(int pos) {
|
||||||
|
version(win32_widgets)
|
||||||
|
SendMessageA(hwnd, PBM_SETPOS, pos, 0);
|
||||||
|
else {
|
||||||
|
current = pos;
|
||||||
|
if(current > max)
|
||||||
|
current = max;
|
||||||
|
redraw();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void setRange(ushort min, ushort max) {
|
||||||
|
version(win32_widgets)
|
||||||
|
SendMessageA(hwnd, PBM_SETRANGE, 0, MAKELONG(min, max));
|
||||||
|
else {
|
||||||
|
this.max = max;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
override int minHeight() { return 10; }
|
||||||
|
}
|
||||||
|
|
||||||
|
class Fieldset : Widget {
|
||||||
|
override int padding() { return 8; }
|
||||||
|
override int margin() { return 4; }
|
||||||
|
|
||||||
|
string legend;
|
||||||
|
/*
|
||||||
|
version(win32_widgets)
|
||||||
|
this(string legend, Widget parent = null) {
|
||||||
|
super(parent);
|
||||||
|
this.legend = legend;
|
||||||
|
parentWindow = parent.parentWindow;
|
||||||
|
createWin32Window(this, "button", legend, BS_GROUPBOX);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
*/
|
||||||
|
this(string legend, Widget parent = null) {
|
||||||
|
super(parent);
|
||||||
|
this.legend = legend;
|
||||||
|
parentWindow = parent.parentWindow;
|
||||||
|
this.paint = (ScreenPainter painter) {
|
||||||
|
painter.fillColor = Color(220, 220, 220);
|
||||||
|
painter.outlineColor = Color.black;
|
||||||
|
painter.drawRectangle(Point(0, 0), width, height);
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
override int maxHeight() {
|
||||||
|
auto m = padding * 2;
|
||||||
|
foreach(child; children)
|
||||||
|
m += child.maxHeight();
|
||||||
|
return m;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
class Menu : Widget {
|
class Menu : Widget {
|
||||||
|
@ -860,8 +1045,7 @@ class Menu : Widget {
|
||||||
addChild(item);
|
addChild(item);
|
||||||
items ~= item;
|
items ~= item;
|
||||||
version(win32_widgets) {
|
version(win32_widgets) {
|
||||||
MainWindow.menuCommandMapping[MainWindow.lastId + 1] = item;
|
AppendMenu(handle, MF_STRING, item.action is null ? 9000 : item.action.id, toStringzInternal(item.label));
|
||||||
AppendMenu(handle, MF_STRING, ++MainWindow.lastId, toStringz(item.label));
|
|
||||||
}
|
}
|
||||||
return item;
|
return item;
|
||||||
}
|
}
|
||||||
|
@ -894,6 +1078,7 @@ class Menu : Widget {
|
||||||
class MenuItem : MouseActivatedWidget {
|
class MenuItem : MouseActivatedWidget {
|
||||||
Menu submenu;
|
Menu submenu;
|
||||||
|
|
||||||
|
Action action;
|
||||||
string label;
|
string label;
|
||||||
|
|
||||||
override int maxHeight() { return Window.lineHeight; }
|
override int maxHeight() { return Window.lineHeight; }
|
||||||
|
@ -910,10 +1095,17 @@ class MenuItem : MouseActivatedWidget {
|
||||||
painter.outlineColor = Color.black;
|
painter.outlineColor = Color.black;
|
||||||
painter.drawText(Point(0, 0), label, Point(width, height), TextAlignment.Center);
|
painter.drawText(Point(0, 0), label, Point(width, height), TextAlignment.Center);
|
||||||
};
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
this(Action action, Window parent = null) {
|
||||||
|
assert(action !is null);
|
||||||
|
this(action.label);
|
||||||
|
this.action = action;
|
||||||
defaultEventHandlers["click"] = (Widget w, Event ev) {
|
defaultEventHandlers["click"] = (Widget w, Event ev) {
|
||||||
auto event = new Event("triggered", this);
|
//auto event = new Event("triggered", this);
|
||||||
event.dispatch();
|
//event.dispatch();
|
||||||
|
foreach(handler; action.triggered)
|
||||||
|
handler();
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1153,6 +1345,20 @@ int[2] getChildPositionRelativeToParentOrigin(Widget c) nothrow {
|
||||||
return [x, y];
|
return [x, y];
|
||||||
}
|
}
|
||||||
|
|
||||||
|
version(win32_widgets)
|
||||||
|
int[2] getChildPositionRelativeToParentHwnd(Widget c) nothrow {
|
||||||
|
int x, y;
|
||||||
|
Widget par = c;
|
||||||
|
while(par) {
|
||||||
|
x += par.x;
|
||||||
|
y += par.y;
|
||||||
|
par = par.parent;
|
||||||
|
if(par !is null && par.hwnd !is null)
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
return [x, y];
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
class TextEdit : Widget {
|
class TextEdit : Widget {
|
||||||
override int heightStretchiness() { return 3; }
|
override int heightStretchiness() { return 3; }
|
||||||
|
@ -1194,7 +1400,7 @@ class TextEdit : Widget {
|
||||||
@property void content(string s) {
|
@property void content(string s) {
|
||||||
_content = s;
|
_content = s;
|
||||||
version(win32_widgets)
|
version(win32_widgets)
|
||||||
SetWindowTextA(hwnd, toStringz(s));
|
SetWindowTextA(hwnd, toStringzInternal(s));
|
||||||
else
|
else
|
||||||
redraw();
|
redraw();
|
||||||
}
|
}
|
||||||
|
@ -1300,6 +1506,7 @@ enum EventType : string {
|
||||||
mouseout = "mouseout",
|
mouseout = "mouseout",
|
||||||
mouseup = "mouseup",
|
mouseup = "mouseup",
|
||||||
mousedown = "mousedown",
|
mousedown = "mousedown",
|
||||||
|
mousemove = "mousemove",
|
||||||
|
|
||||||
keydown = "keydown",
|
keydown = "keydown",
|
||||||
keyup = "keyup",
|
keyup = "keyup",
|
||||||
|
@ -1340,6 +1547,7 @@ class Event {
|
||||||
int clientY;
|
int clientY;
|
||||||
|
|
||||||
int button;
|
int button;
|
||||||
|
Key key;
|
||||||
dchar character;
|
dchar character;
|
||||||
|
|
||||||
private bool isBubbling;
|
private bool isBubbling;
|
||||||
|
@ -1439,10 +1647,15 @@ Widget widgetAtPoint(Widget starting, int x, int y) {
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
version(Windows) {
|
version(win32_widgets) {
|
||||||
|
import std.c.windows.windows;
|
||||||
|
// import win32.commctrl;
|
||||||
|
// import win32.winuser;
|
||||||
|
|
||||||
pragma(lib, "comctl32");
|
pragma(lib, "comctl32");
|
||||||
|
|
||||||
static this() {
|
static this() {
|
||||||
|
// http://msdn.microsoft.com/en-us/library/windows/desktop/bb775507(v=vs.85).aspx
|
||||||
INITCOMMONCONTROLSEX ic;
|
INITCOMMONCONTROLSEX ic;
|
||||||
ic.dwSize = cast(DWORD) ic.sizeof;
|
ic.dwSize = cast(DWORD) ic.sizeof;
|
||||||
ic.dwICC = ICC_WIN95_CLASSES | ICC_BAR_CLASSES | ICC_PROGRESS_CLASS | ICC_COOL_CLASSES;
|
ic.dwICC = ICC_WIN95_CLASSES | ICC_BAR_CLASSES | ICC_PROGRESS_CLASS | ICC_COOL_CLASSES;
|
||||||
|
@ -1609,6 +1822,38 @@ enum {
|
||||||
TB_GETTEXTROWS // = WM_USER + 61
|
TB_GETTEXTROWS // = WM_USER + 61
|
||||||
}
|
}
|
||||||
|
|
||||||
|
enum {
|
||||||
|
CCM_FIRST = 0x2000,
|
||||||
|
CCM_LAST = CCM_FIRST + 0x200,
|
||||||
|
CCM_SETBKCOLOR = 8193,
|
||||||
|
CCM_SETCOLORSCHEME = 8194,
|
||||||
|
CCM_GETCOLORSCHEME = 8195,
|
||||||
|
CCM_GETDROPTARGET = 8196,
|
||||||
|
CCM_SETUNICODEFORMAT = 8197,
|
||||||
|
CCM_GETUNICODEFORMAT = 8198,
|
||||||
|
CCM_SETVERSION = 0x2007,
|
||||||
|
CCM_GETVERSION = 0x2008,
|
||||||
|
CCM_SETNOTIFYWINDOW = 0x2009
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
enum {
|
||||||
|
PBM_SETRANGE = WM_USER + 1,
|
||||||
|
PBM_SETPOS,
|
||||||
|
PBM_DELTAPOS,
|
||||||
|
PBM_SETSTEP,
|
||||||
|
PBM_STEPIT, // = WM_USER + 5
|
||||||
|
PBM_SETRANGE32 = 1030,
|
||||||
|
PBM_GETRANGE,
|
||||||
|
PBM_GETPOS,
|
||||||
|
PBM_SETBARCOLOR, // = 1033
|
||||||
|
PBM_SETBKCOLOR = CCM_SETBKCOLOR
|
||||||
|
}
|
||||||
|
|
||||||
|
enum {
|
||||||
|
PBS_SMOOTH = 1,
|
||||||
|
PBS_VERTICAL = 4
|
||||||
|
}
|
||||||
|
|
||||||
enum {
|
enum {
|
||||||
ICC_LISTVIEW_CLASSES = 1,
|
ICC_LISTVIEW_CLASSES = 1,
|
||||||
|
@ -1628,3 +1873,31 @@ enum {
|
||||||
enum WM_USER = 1024;
|
enum WM_USER = 1024;
|
||||||
enum SB_SETTEXT = WM_USER + 1; // SET TEXT A. It is +11 for W
|
enum SB_SETTEXT = WM_USER + 1; // SET TEXT A. It is +11 for W
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
version(win32_widgets)
|
||||||
|
enum GenericIcons : ushort {
|
||||||
|
New = STD_FILENEW,
|
||||||
|
Open = STD_FILEOPEN,
|
||||||
|
Save = STD_FILESAVE,
|
||||||
|
}
|
||||||
|
else
|
||||||
|
enum GenericIcons : ushort {
|
||||||
|
New, Open, Save
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
http://msdn.microsoft.com/en-us/library/windows/desktop/bb775947%28v=vs.85%29.aspx#check_boxes
|
||||||
|
http://msdn.microsoft.com/en-us/library/windows/desktop/ms633574%28v=vs.85%29.aspx
|
||||||
|
http://msdn.microsoft.com/en-us/library/windows/desktop/bb775943%28v=vs.85%29.aspx
|
||||||
|
http://msdn.microsoft.com/en-us/library/windows/desktop/bb775951%28v=vs.85%29.aspx
|
||||||
|
http://msdn.microsoft.com/en-us/library/windows/desktop/ms632680%28v=vs.85%29.aspx
|
||||||
|
http://msdn.microsoft.com/en-us/library/windows/desktop/ms644996%28v=vs.85%29.aspx#message_box
|
||||||
|
http://www.sbin.org/doc/Xlib/chapt_03.html
|
||||||
|
|
||||||
|
http://msdn.microsoft.com/en-us/library/windows/desktop/bb760433%28v=vs.85%29.aspx
|
||||||
|
http://msdn.microsoft.com/en-us/library/windows/desktop/bb760446%28v=vs.85%29.aspx
|
||||||
|
http://msdn.microsoft.com/en-us/library/windows/desktop/bb760443%28v=vs.85%29.aspx
|
||||||
|
http://msdn.microsoft.com/en-us/library/windows/desktop/bb760476%28v=vs.85%29.aspx
|
||||||
|
*/
|
||||||
|
|
Loading…
Reference in New Issue