linux build fixes

This commit is contained in:
Vadim Lopatin 2014-04-15 14:34:14 +04:00
parent f35b63ef95
commit 4ddccd9f6a
5 changed files with 383 additions and 377 deletions

View File

@ -179,6 +179,7 @@
<Compile Include="src\dlangui\widgets\tabs.d" /> <Compile Include="src\dlangui\widgets\tabs.d" />
<Compile Include="src\dlangui\graphics\resources.d" /> <Compile Include="src\dlangui\graphics\resources.d" />
<Compile Include="src\dlangui\widgets\menu.d" /> <Compile Include="src\dlangui\widgets\menu.d" />
<Compile Include="src\dlangui\widgets\popup.d" />
</ItemGroup> </ItemGroup>
<ItemGroup> <ItemGroup>
<Folder Include="src\dlangui\platforms\x11\" /> <Folder Include="src\dlangui\platforms\x11\" />

View File

@ -1,14 +1,14 @@
module dlangui.all; module dlangui.all;
public import dlangui.core.logger; public import dlangui.core.logger;
public import dlangui.core.types; public import dlangui.core.types;
public import dlangui.platforms.common.platform; public import dlangui.platforms.common.platform;
public import dlangui.graphics.images; public import dlangui.graphics.images;
public import dlangui.widgets.widget; public import dlangui.widgets.widget;
public import dlangui.widgets.controls; public import dlangui.widgets.controls;
public import dlangui.widgets.layouts; public import dlangui.widgets.layouts;
public import dlangui.widgets.lists; public import dlangui.widgets.lists;
public import dlangui.widgets.tabs; public import dlangui.widgets.tabs;
public import dlangui.widgets.menu; public import dlangui.widgets.menu;
public import dlangui.graphics.fonts; public import dlangui.graphics.fonts;
public import dlangui.core.i18n; public import dlangui.core.i18n;

View File

@ -1,99 +1,99 @@
module dlangui.core.types; module dlangui.core.types;
import std.algorithm; import std.algorithm;
struct Point { struct Point {
int x; int x;
int y; int y;
this(int x0, int y0) { this(int x0, int y0) {
x = x0; x = x0;
y = y0; y = y0;
} }
} }
struct Rect { struct Rect {
int left; int left;
int top; int top;
int right; int right;
int bottom; int bottom;
@property int middlex() { return (left + right) / 2; } @property int middlex() { return (left + right) / 2; }
@property int middley() { return (top + bottom) / 2; } @property int middley() { return (top + bottom) / 2; }
void offset(int dx, int dy) { void offset(int dx, int dy) {
left += dx; left += dx;
right += dx; right += dx;
top += dy; top += dy;
bottom += dy; bottom += dy;
} }
/// for all fields, sets this.field to rc.field if rc.field > this.field /// for all fields, sets this.field to rc.field if rc.field > this.field
void setMax(Rect rc) { void setMax(Rect rc) {
if (left < rc.left) if (left < rc.left)
left = rc.left; left = rc.left;
if (right < rc.right) if (right < rc.right)
right = rc.right; right = rc.right;
if (top < rc.top) if (top < rc.top)
top = rc.top; top = rc.top;
if (bottom < rc.bottom) if (bottom < rc.bottom)
bottom = rc.bottom; bottom = rc.bottom;
} }
@property int width() { return right - left; } @property int width() { return right - left; }
@property int height() { return bottom - top; } @property int height() { return bottom - top; }
this(int x0, int y0, int x1, int y1) { this(int x0, int y0, int x1, int y1) {
left = x0; left = x0;
top = y0; top = y0;
right = x1; right = x1;
bottom = y1; bottom = y1;
} }
@property bool empty() { @property bool empty() {
return right <= left || bottom <= top; return right <= left || bottom <= top;
} }
void moveBy(int deltax, int deltay) { void moveBy(int deltax, int deltay) {
left += deltax; left += deltax;
right += deltax; right += deltax;
top += deltay; top += deltay;
bottom += deltay; bottom += deltay;
} }
/// moves this rect to fit rc bounds, retaining the same size /// moves this rect to fit rc bounds, retaining the same size
void moveToFit(ref Rect rc) { void moveToFit(ref Rect rc) {
if (right > rc.right) if (right > rc.right)
moveBy(rc.right - right, 0); moveBy(rc.right - right, 0);
if (bottom > rc.bottom) if (bottom > rc.bottom)
moveBy(0, rc.bottom - bottom); moveBy(0, rc.bottom - bottom);
if (left < rc.left) if (left < rc.left)
moveBy(rc.left - left, 0); moveBy(rc.left - left, 0);
if (top < rc.top) if (top < rc.top)
moveBy(0, rc.top - top); moveBy(0, rc.top - top);
} }
/// updates this rect to intersection with rc, returns true if result is non empty /// updates this rect to intersection with rc, returns true if result is non empty
bool intersect(Rect rc) { bool intersect(Rect rc) {
if (left < rc.left) if (left < rc.left)
left = rc.left; left = rc.left;
if (top < rc.top) if (top < rc.top)
top = rc.top; top = rc.top;
if (right > rc.right) if (right > rc.right)
right = rc.right; right = rc.right;
if (bottom > rc.bottom) if (bottom > rc.bottom)
bottom = rc.bottom; bottom = rc.bottom;
return right > left && bottom > top; return right > left && bottom > top;
} }
/// returns true if this rect has nonempty intersection with rc /// returns true if this rect has nonempty intersection with rc
bool intersects(Rect rc) { bool intersects(Rect rc) {
if (rc.left >= right || rc.top >= bottom || rc.right <= left || rc.bottom <= top) if (rc.left >= right || rc.top >= bottom || rc.right <= left || rc.bottom <= top)
return false; return false;
return true; return true;
} }
/// returns true if point is inside of this rectangle /// returns true if point is inside of this rectangle
bool isPointInside(Point pt) { bool isPointInside(Point pt) {
return pt.x >= left && pt.x < right && pt.y >= top && pt.y < bottom; return pt.x >= left && pt.x < right && pt.y >= top && pt.y < bottom;
} }
/// returns true if point is inside of this rectangle /// returns true if point is inside of this rectangle
bool isPointInside(int x, int y) { bool isPointInside(int x, int y) {
return x >= left && x < right && y >= top && y < bottom; return x >= left && x < right && y >= top && y < bottom;
} }
} }
/// character glyph /// character glyph
align(1) align(1)
struct Glyph struct Glyph
{ {
version (USE_OPENGL) { version (USE_OPENGL) {
@ -117,84 +117,84 @@ struct Glyph
///< 12: glyph data, arbitrary size ///< 12: glyph data, arbitrary size
ubyte[] glyph; ubyte[] glyph;
} }
class RefCountedObject { class RefCountedObject {
protected int _refCount; protected int _refCount;
@property int refCount() const { return _refCount; } @property int refCount() const { return _refCount; }
void addRef() { void addRef() {
_refCount++; _refCount++;
} }
void releaseRef() { void releaseRef() {
if (--_refCount == 0) if (--_refCount == 0)
destroy(this); destroy(this);
} }
~this() {} ~this() {}
} }
struct Ref(T) { // if (T is RefCountedObject) struct Ref(T) { // if (T is RefCountedObject)
private T _data; private T _data;
alias get this; alias get this;
@property bool isNull() const { return _data is null; } @property bool isNull() const { return _data is null; }
@property int refCount() const { return _data !is null ? _data.refCount : 0; } @property int refCount() const { return _data !is null ? _data.refCount : 0; }
this(T data) { this(T data) {
_data = data; _data = data;
if (_data !is null) if (_data !is null)
_data.addRef(); _data.addRef();
} }
this(this) { this(this) {
if (_data !is null) if (_data !is null)
_data.addRef(); _data.addRef();
} }
ref Ref opAssign(ref Ref data) { ref Ref opAssign(ref Ref data) {
if (data._data == _data) if (data._data == _data)
return this; return this;
if (_data !is null) if (_data !is null)
_data.releaseRef(); _data.releaseRef();
_data = data._data; _data = data._data;
if (_data !is null) if (_data !is null)
_data.addRef(); _data.addRef();
return this; return this;
} }
ref Ref opAssign(Ref data) { ref Ref opAssign(Ref data) {
if (data._data == _data) if (data._data == _data)
return this; return this;
if (_data !is null) if (_data !is null)
_data.releaseRef(); _data.releaseRef();
_data = data._data; _data = data._data;
if (_data !is null) if (_data !is null)
_data.addRef(); _data.addRef();
return this; return this;
} }
ref Ref opAssign(T data) { ref Ref opAssign(T data) {
if (data == _data) if (data == _data)
return this; return this;
if (_data !is null) if (_data !is null)
_data.releaseRef(); _data.releaseRef();
_data = data; _data = data;
if (_data !is null) if (_data !is null)
_data.addRef(); _data.addRef();
return this; return this;
} }
void clear() { void clear() {
if (_data !is null) { if (_data !is null) {
_data.releaseRef(); _data.releaseRef();
_data = null; _data = null;
} }
} }
@property T get() { @property T get() {
return _data; return _data;
} }
@property const(T) get() const { @property const(T) get() const {
return _data; return _data;
} }
~this() { ~this() {
if (_data !is null) if (_data !is null)
_data.releaseRef(); _data.releaseRef();
} }
} }
// some utility functions // some utility functions
string fromStringz(const(char[]) s) { string fromStringz(const(char[]) s) {
if (s is null) if (s is null)
return null; return null;

View File

@ -220,7 +220,7 @@ class Window {
private bool checkRemoveTracking(MouseEvent event) { private bool checkRemoveTracking(MouseEvent event) {
import std.algorithm; import std.algorithm;
bool res = false; bool res = false;
for(int i = _mouseTrackingWidgets.length - 1; i >=0; i--) { for(int i = cast(int)_mouseTrackingWidgets.length - 1; i >=0; i--) {
Widget w = _mouseTrackingWidgets[i]; Widget w = _mouseTrackingWidgets[i];
if (!isChild(w)) { if (!isChild(w)) {
// std.algorithm.remove does not work for me // std.algorithm.remove does not work for me

View File

@ -1,204 +1,209 @@
module dlangui.widgets.menu; module dlangui.widgets.menu;
import dlangui.core.events; import dlangui.core.events;
import dlangui.widgets.controls; import dlangui.widgets.controls;
import dlangui.widgets.layouts; import dlangui.widgets.layouts;
import dlangui.widgets.lists; import dlangui.widgets.lists;
import dlangui.widgets.popup; import dlangui.widgets.popup;
/// menu item properties /// menu item properties
class MenuItem { class MenuItem {
protected bool _checkable; protected bool _checkable;
protected bool _checked; protected bool _checked;
protected bool _enabled; protected bool _enabled;
protected Action _action; protected Action _action;
protected MenuItem[] _subitems; protected MenuItem[] _subitems;
/// item action id, 0 if no action /// item action id, 0 if no action
@property int id() { return _action is null ? 0 : _action.id; } @property int id() { return _action is null ? 0 : _action.id; }
/// returns count of submenu items /// returns count of submenu items
@property int subitemCount() { @property int subitemCount() {
return cast(int)_subitems.length; return cast(int)_subitems.length;
} }
/// returns submenu item by index /// returns submenu item by index
MenuItem subitem(int index) { MenuItem subitem(int index) {
return _subitems[index]; return _subitems[index];
} }
/// adds submenu item /// adds submenu item
MenuItem add(MenuItem subitem) { MenuItem add(MenuItem subitem) {
_subitems ~= subitem; _subitems ~= subitem;
return this; return this;
} }
/// adds submenu item from action /// adds submenu item from action
MenuItem add(Action subitemAction) { MenuItem add(Action subitemAction) {
_subitems ~= new MenuItem(subitemAction); _subitems ~= new MenuItem(subitemAction);
return this; return this;
} }
/// returns true if item is submenu (contains subitems) /// returns true if item is submenu (contains subitems)
@property bool isSubmenu() { @property bool isSubmenu() {
return _subitems.length > 0; return _subitems.length > 0;
} }
/// returns item label /// returns item label
@property UIString label() { @property UIString label() {
return _action.labelValue; return _action.labelValue;
} }
/// returns item action /// returns item action
@property const(Action) action() const { return _action; } @property const(Action) action() const { return _action; }
/// sets item action /// sets item action
@property MenuItem action(Action a) { _action = a; return this; } @property MenuItem action(Action a) { _action = a; return this; }
this() { this() {
_enabled = true; _enabled = true;
} }
this(Action action) { this(Action action) {
_action = action; _action = action;
_enabled = true; _enabled = true;
} }
~this() { ~this() {
// TODO // TODO
} }
} }
/// widget to draw menu item /// widget to draw menu item
class MenuItemWidget : HorizontalLayout { class MenuItemWidget : HorizontalLayout {
protected MenuItem _item; protected MenuItem _item;
protected TextWidget _label; protected TextWidget _label;
@property MenuItem item() { return _item; } @property MenuItem item() { return _item; }
this(MenuItem item) { this(MenuItem item) {
id="menuitem"; id="menuitem";
_item = item; _item = item;
styleId = "MENU_ITEM"; styleId = "MENU_ITEM";
_label = new TextWidget("MENU_LABEL"); _label = new TextWidget("MENU_LABEL");
_label.text = _item.label; _label.text = _item.label;
addChild(_label); addChild(_label);
trackHover = true; trackHover = true;
} }
} }
/// base class for menus /// base class for menus
class MenuWidgetBase : ListWidget { class MenuWidgetBase : ListWidget {
protected MenuWidgetBase _parentMenu; protected MenuWidgetBase _parentMenu;
protected MenuItem _item; protected MenuItem _item;
protected PopupMenu _openedMenu; protected PopupMenu _openedMenu;
protected PopupWidget _openedPopup; protected PopupWidget _openedPopup;
protected bool delegate(MenuItem item) _onMenuItemClickListener; protected bool delegate(MenuItem item) _onMenuItemClickListener;
/// menu item click listener /// menu item click listener
@property bool delegate(MenuItem item) onMenuItemListener() { return _onMenuItemClickListener; } @property bool delegate(MenuItem item) onMenuItemListener() { return _onMenuItemClickListener; }
/// menu item click listener /// menu item click listener
@property MenuWidgetBase onMenuItemListener(bool delegate(MenuItem item) listener) { _onMenuItemClickListener = listener; return this; } @property MenuWidgetBase onMenuItemListener(bool delegate(MenuItem item) listener) { _onMenuItemClickListener = listener; return this; }
this(MenuWidgetBase parentMenu, MenuItem item, Orientation orientation) { this(MenuWidgetBase parentMenu, MenuItem item, Orientation orientation) {
_parentMenu = parentMenu; _parentMenu = parentMenu;
_item = item; _item = item;
this.orientation = orientation; this.orientation = orientation;
id = "popup_menu"; id = "popup_menu";
styleId = "POPUP_MENU"; styleId = "POPUP_MENU";
WidgetListAdapter adapter = new WidgetListAdapter(); WidgetListAdapter adapter = new WidgetListAdapter();
for (int i=0; i < _item.subitemCount; i++) { for (int i=0; i < _item.subitemCount; i++) {
MenuItem subitem = _item.subitem(i); MenuItem subitem = _item.subitem(i);
MenuItemWidget widget = new MenuItemWidget(subitem); MenuItemWidget widget = new MenuItemWidget(subitem);
if (orientation == Orientation.Horizontal) if (orientation == Orientation.Horizontal)
widget.styleId = "MAIN_MENU_ITEM"; widget.styleId = "MAIN_MENU_ITEM";
adapter.widgets.add(widget); adapter.widgets.add(widget);
} }
ownAdapter = adapter; ownAdapter = adapter;
} }
protected void onPopupClosed(PopupWidget p) { protected void onPopupClosed(PopupWidget p) {
_openedPopup = null; _openedPopup = null;
_openedMenu = null; _openedMenu = null;
selectItem(-1); selectItem(-1);
} }
protected void openSubmenu(MenuItemWidget itemWidget) { protected void openSubmenu(MenuItemWidget itemWidget) {
if (_openedPopup !is null) { if (_openedPopup !is null) {
_openedPopup.close(); _openedPopup.close();
} }
PopupMenu popupMenu = new PopupMenu(itemWidget.item, this); PopupMenu popupMenu = new PopupMenu(itemWidget.item, this);
PopupWidget popup = window.showPopup(popupMenu, itemWidget, orientation == Orientation.Horizontal ? PopupAlign.Below : PopupAlign.Right); PopupWidget popup = window.showPopup(popupMenu, itemWidget, orientation == Orientation.Horizontal ? PopupAlign.Below : PopupAlign.Right);
popup.onPopupCloseListener = &onPopupClosed; popup.onPopupCloseListener = &onPopupClosed;
popup.flags = PopupFlags.CloseOnClickOutside; popup.flags = PopupFlags.CloseOnClickOutside;
_openedPopup = popup; _openedPopup = popup;
_openedMenu = popupMenu; _openedMenu = popupMenu;
} }
/// override to handle change of selection /// override to handle change of selection
override protected void selectionChanged(int index, int previouslySelectedItem = -1) { override protected void selectionChanged(int index, int previouslySelectedItem = -1) {
MenuItemWidget itemWidget = index >= 0 ? cast(MenuItemWidget)_adapter.itemWidget(index) : null; MenuItemWidget itemWidget = index >= 0 ? cast(MenuItemWidget)_adapter.itemWidget(index) : null;
MenuItemWidget prevWidget = previouslySelectedItem >= 0 ? cast(MenuItemWidget)_adapter.itemWidget(previouslySelectedItem) : null;
if (prevWidget !is null) {
if (_openedPopup !is null)
_openedPopup.close();
}
if (itemWidget !is null) { if (itemWidget !is null) {
if (itemWidget.item.isSubmenu()) { if (itemWidget.item.isSubmenu()) {
if (_selectOnHover) { if (_selectOnHover) {
openSubmenu(itemWidget); openSubmenu(itemWidget);
} }
} else { } else {
// normal item // normal item
} }
} }
} }
protected void onMenuItem(MenuItem item) { protected void onMenuItem(MenuItem item) {
if (_openedPopup !is null) { if (_openedPopup !is null) {
_openedPopup.close(); _openedPopup.close();
_openedPopup = null; _openedPopup = null;
} }
if (_parentMenu !is null) if (_parentMenu !is null)
_parentMenu.onMenuItem(item); _parentMenu.onMenuItem(item);
else { else {
// top level handling // top level handling
Log.d("onMenuItem ", item.id); Log.d("onMenuItem ", item.id);
selectItem(-1); selectItem(-1);
selectOnHover = false; selectOnHover = false;
bool delegate(MenuItem item) listener = _onMenuItemClickListener; bool delegate(MenuItem item) listener = _onMenuItemClickListener;
PopupWidget popup = cast(PopupWidget)parent; PopupWidget popup = cast(PopupWidget)parent;
if (popup) if (popup)
popup.close(); popup.close();
// this pointer now can be invalid - if popup removed // this pointer now can be invalid - if popup removed
if (listener !is null) if (listener !is null)
listener(item); listener(item);
} }
} }
/// override to handle mouse up on item /// override to handle mouse up on item
override protected void itemClicked(int index) { override protected void itemClicked(int index) {
MenuItemWidget itemWidget = index >= 0 ? cast(MenuItemWidget)_adapter.itemWidget(index) : null; MenuItemWidget itemWidget = index >= 0 ? cast(MenuItemWidget)_adapter.itemWidget(index) : null;
if (itemWidget !is null) { if (itemWidget !is null) {
Log.d("Menu Item clicked ", itemWidget.item.action.id); Log.d("Menu Item clicked ", itemWidget.item.action.id);
if (itemWidget.item.isSubmenu()) { if (itemWidget.item.isSubmenu()) {
// submenu clicked // submenu clicked
if (_clickOnButtonDown && _openedPopup !is null && _openedMenu._item is itemWidget.item) { if (_clickOnButtonDown && _openedPopup !is null && _openedMenu._item is itemWidget.item) {
// second click on main menu opened item // second click on main menu opened item
_openedPopup.close(); _openedPopup.close();
_openedPopup = null; _openedPopup = null;
selectItem(-1); selectItem(-1);
selectOnHover = false; selectOnHover = false;
} else { } else {
openSubmenu(itemWidget); openSubmenu(itemWidget);
selectOnHover = true; selectOnHover = true;
} }
} else { } else {
// normal item // normal item
onMenuItem(itemWidget.item); onMenuItem(itemWidget.item);
} }
} }
} }
} }
/// main menu (horizontal) /// main menu (horizontal)
class MainMenu : MenuWidgetBase { class MainMenu : MenuWidgetBase {
this(MenuItem item) { this(MenuItem item) {
super(null, item, Orientation.Horizontal); super(null, item, Orientation.Horizontal);
id = "MAIN_MENU"; id = "MAIN_MENU";
styleId = "MAIN_MENU"; styleId = "MAIN_MENU";
_clickOnButtonDown = true; _clickOnButtonDown = true;
} }
} }
/// popup menu widget (vertical layout of items) /// popup menu widget (vertical layout of items)
class PopupMenu : MenuWidgetBase { class PopupMenu : MenuWidgetBase {
this(MenuItem item, MenuWidgetBase parentMenu = null) { this(MenuItem item, MenuWidgetBase parentMenu = null) {
super(parentMenu, item, Orientation.Vertical); super(parentMenu, item, Orientation.Vertical);
id = "POPUP_MENU"; id = "POPUP_MENU";
styleId = "POPUP_MENU"; styleId = "POPUP_MENU";
selectOnHover = true; selectOnHover = true;
} }
} }