Re-add minwin gtk example
This commit is contained in:
parent
bd19bcacf4
commit
5967eacdf0
52 changed files with 35078 additions and 0 deletions
279
samples/minwin_gtk/minwin/component.d
Normal file
279
samples/minwin_gtk/minwin/component.d
Normal file
|
@ -0,0 +1,279 @@
|
|||
/* MinWin Component class
|
||||
*
|
||||
* A Component is the root of the widget inheritance tree.
|
||||
*
|
||||
* Written by Ben Hinkle and released to the public domain, as
|
||||
* explained at http://creativecommons.org/licenses/publicdomain
|
||||
* Report comments and bugs at dsource: http://www.dsource.org/projects/minwin
|
||||
*/
|
||||
|
||||
module minwin.component;
|
||||
|
||||
public {
|
||||
import minwin.multidg;
|
||||
import minwin.geometry;
|
||||
import minwin.peer;
|
||||
}
|
||||
private {
|
||||
import minwin.event;
|
||||
import minwin.layout;
|
||||
import minwin.logging;
|
||||
}
|
||||
|
||||
abstract class Component {
|
||||
|
||||
// Peer management
|
||||
mixin PeerMixin!();
|
||||
|
||||
// disposePeer will dipose of the system resource associated
|
||||
// with this object if it owns the peer and the object does
|
||||
// not have any parent. It is assumed that an object with a
|
||||
// parent will have its peer disposed when the parent is disposed.
|
||||
void disposePeer();
|
||||
|
||||
PeerForAdd getPeerForAdd() { return null; }
|
||||
|
||||
void getPeerOffset(inout int x, inout int y) {
|
||||
x = 0;
|
||||
y = 0;
|
||||
}
|
||||
|
||||
void dispose() {
|
||||
Component ch = child;
|
||||
while (ch !is null) {
|
||||
ch.dispose();
|
||||
ch = ch.next;
|
||||
}
|
||||
disposePeer();
|
||||
}
|
||||
|
||||
// Name property used for resource lookup on X and debugging
|
||||
char[] name;
|
||||
|
||||
// Application data associative array for user data
|
||||
void*[char[]] userdata;
|
||||
|
||||
void doCommand(int cmd) {
|
||||
if (parent)
|
||||
parent.doCommand(cmd);
|
||||
}
|
||||
|
||||
void requestFocus() {}
|
||||
|
||||
// size management
|
||||
void getMinimumSize(inout int width, inout int height) {
|
||||
//todo: ask layout
|
||||
width = 0;
|
||||
height = 0;
|
||||
}
|
||||
void getMaximumSize(inout int width, inout int height) {
|
||||
//todo: ask layout
|
||||
width = int.max;
|
||||
height = int.max;
|
||||
}
|
||||
abstract void getBounds(inout Rect r);
|
||||
abstract void setBounds(inout Rect r);
|
||||
Rect bounds() {
|
||||
Rect r;
|
||||
getBounds(r);
|
||||
return r;
|
||||
}
|
||||
void bounds(Rect r) {
|
||||
setBounds(r);
|
||||
}
|
||||
void getLayoutBounds(inout Rect r) {
|
||||
Point s = size;
|
||||
version(LOG)log.writefln("getLayoutBounds got size %d %d",s.x,s.y);
|
||||
r.LTWH(0,0,s.x,s.y);
|
||||
}
|
||||
void size(Point s);
|
||||
Point size() {
|
||||
Rect bounds;
|
||||
getBounds(bounds);
|
||||
version(LOG)log.writefln("size function got width,height %d %d",bounds.width,bounds.height);
|
||||
Point res;
|
||||
res.x = bounds.width;
|
||||
res.y = bounds.height;
|
||||
return res;
|
||||
}
|
||||
int width() {
|
||||
Rect bounds;
|
||||
getBounds(bounds);
|
||||
return bounds.width;
|
||||
}
|
||||
int height() {
|
||||
Rect bounds;
|
||||
getBounds(bounds);
|
||||
return bounds.height;
|
||||
}
|
||||
|
||||
// property to request a particular width no matter what layout
|
||||
int userPreferredWidth_data;
|
||||
final int userPreferredWidth() { return userPreferredWidth_data; }
|
||||
void userPreferredWidth(int width) {
|
||||
userPreferredWidth_data = width;
|
||||
// childLayoutDirty = true;
|
||||
// repaint();
|
||||
}
|
||||
|
||||
// property to request a particular height no matter what layout
|
||||
int userPreferredHeight_data;
|
||||
final int userPreferredHeight() { return userPreferredHeight_data; }
|
||||
void userPreferredHeight(int height) {
|
||||
userPreferredHeight_data = height;
|
||||
// childLayoutDirty = true;
|
||||
// repaint();
|
||||
}
|
||||
|
||||
void userPreferredSize(int width, int height) {
|
||||
userPreferredHeight = height;
|
||||
userPreferredWidth = width;
|
||||
}
|
||||
|
||||
Point preferredSize(){
|
||||
Point p;
|
||||
if (layoutMgr) {
|
||||
p = layoutMgr.preferredSize(this);
|
||||
}
|
||||
if (userPreferredWidth() > 0)
|
||||
p.x = userPreferredWidth();
|
||||
if (userPreferredHeight() > 0)
|
||||
p.y = userPreferredHeight();
|
||||
return p;
|
||||
}
|
||||
|
||||
// visible property
|
||||
void visible(bool vis);
|
||||
bool visible();
|
||||
|
||||
// enabled property
|
||||
void enabled(bool ena);
|
||||
bool enabled();
|
||||
|
||||
Component getRootAncestor() {
|
||||
Component top = this;
|
||||
while (top.parent !is null) {
|
||||
top = top.parent;
|
||||
}
|
||||
return top;
|
||||
}
|
||||
|
||||
// hierarchy management
|
||||
Component parent;
|
||||
Component child;
|
||||
Component next;
|
||||
Component prev;
|
||||
|
||||
Component last() {
|
||||
return child ? child.prev : null;
|
||||
}
|
||||
|
||||
// loop over children
|
||||
int opApply(int delegate(inout Component c) dg) {
|
||||
int res = 0;
|
||||
Component c = child;
|
||||
if (c) {
|
||||
do {
|
||||
res = dg(c);
|
||||
c = c.next;
|
||||
} while(!res && c !is child);
|
||||
}
|
||||
return res;
|
||||
}
|
||||
|
||||
// link two component as siblings.
|
||||
// should an api be exposed to re-arrange without getting the peer?
|
||||
void link(Component left, Component right) {
|
||||
left.next = right;
|
||||
right.prev = left;
|
||||
}
|
||||
|
||||
void opCatAssign(Component x) {
|
||||
addChild(x);
|
||||
}
|
||||
|
||||
void addChild(Component x) {
|
||||
x.parent = this;
|
||||
if (!child) {
|
||||
child = x;
|
||||
x.prev = x.next = x;
|
||||
} else {
|
||||
link(last,x);
|
||||
link(x,child);
|
||||
}
|
||||
}
|
||||
|
||||
void removeChild(Component x) {
|
||||
Component old = last;
|
||||
if (x is child) {
|
||||
if (child is last)
|
||||
child = null;
|
||||
else
|
||||
child = child.next;
|
||||
}
|
||||
link(x.prev,x.next);
|
||||
x.prev = null;
|
||||
x.next = null;
|
||||
x.parent = null;
|
||||
}
|
||||
|
||||
// layout management. TODO: invalidate and repaint on change
|
||||
LayoutManager layoutMgr;
|
||||
bool childLayoutDirty = true;
|
||||
|
||||
bool parentOwnsLayout_data = true;
|
||||
bool parentOwnsLayout() { return parentOwnsLayout_data; }
|
||||
void parentOwnsLayout(bool x) {
|
||||
parentOwnsLayout_data = x;
|
||||
if (parent) {
|
||||
parent.childLayoutDirty = true;
|
||||
parent.repaint();
|
||||
}
|
||||
}
|
||||
|
||||
bool parentOwnsVisibility = true;
|
||||
|
||||
void layout(bool validateParent) {
|
||||
if (parent && validateParent)
|
||||
parent.layout(true);
|
||||
if (childLayoutDirty) {
|
||||
if (layoutMgr)
|
||||
layoutMgr.layout(this);
|
||||
childLayoutDirty = false;
|
||||
}
|
||||
foreach( Component ch; this) {
|
||||
ch.layout(false);
|
||||
}
|
||||
}
|
||||
|
||||
void pack() {
|
||||
int width,height;
|
||||
Point s;
|
||||
if (layoutMgr) {
|
||||
s = layoutMgr.preferredSize(this);
|
||||
version(LOG) log.writefln("preferred size %d %d",s.x,s.y);
|
||||
size = s;
|
||||
childLayoutDirty = true;
|
||||
version(LOG) log.printf("in pack about to repaint %x\n",this);
|
||||
repaint();
|
||||
version(LOG) log.printf("in pack done repaint about to layout %x\n",this);
|
||||
layout(false);
|
||||
version(LOG) log.printf("in pack done layout %x\n",this);
|
||||
}
|
||||
}
|
||||
|
||||
// painting and graphics context management
|
||||
void repaint() {
|
||||
version(LOG) log.printf("in component.repaint for %x\n",this);
|
||||
foreach ( Component c; this) {
|
||||
version(LOG) log.printf(" repaint for child %x of %x\n",c,this);
|
||||
c.repaint();
|
||||
}
|
||||
}
|
||||
bool clearBackgroundOnPaint = true;
|
||||
void repaint(inout Rect r) {}
|
||||
}
|
||||
|
||||
class WindowChild : Component {
|
||||
WindowChildPeer getPeer() { return null; }
|
||||
}
|
Loading…
Add table
Add a link
Reference in a new issue